Pthread互斥锁由不同的线程解锁
Posted
技术标签:
【中文标题】Pthread互斥锁由不同的线程解锁【英文标题】:Pthread Mutex lock unlock by different threads 【发布时间】:2011-07-24 05:00:12 【问题描述】:一个幼稚的问题..
我之前读到过 -“MUTEX 只能由锁定它的线程解锁。”
但我编写了一个程序,其中 THREAD1 锁定 mutexVar 并进入睡眠状态。然后THREAD2可以直接解锁mutexVar做一些操作并返回。
==> 我知道每个人都说我为什么这样做??但我的问题是 - 这是 MUTEX 的正确行为吗??
==> 添加示例代码
void *functionC()
pthread_mutex_lock( &mutex1 );
counter++;
sleep(10);
printf("Thread01: Counter value: %d\n",counter);
pthread_mutex_unlock( &mutex1 );
void *functionD()
pthread_mutex_unlock( &mutex1 );
pthread_mutex_lock( &mutex1 );
counter=10;
printf("Counter value: %d\n",counter);
int main()
int rc1, rc2;
pthread_t thread1, thread2;
if(pthread_mutex_init(&mutex1, NULL))
printf("Error while using pthread_mutex_init\n");
if( (rc1=pthread_create( &thread1, NULL, &functionC, NULL)) )
printf("Thread creation failed: %d\n", rc1);
if( (rc2=pthread_create( &thread2, NULL, &functionD, NULL)) )
printf("Thread creation failed: %d\n", rc2);
【问题讨论】:
@Santiago - 添加了示例代码.. NO -- 但值为 1 的 SEMAPHORE 可以像互斥锁一样,并且可以从不同的线程解锁。但是,您可能需要使用互斥锁来保护信号量上的操作,以阻止其值超过 1。 【参考方案1】:您所做的根本不合法,并且行为未定义。互斥锁只排除遵守规则的线程。如果您试图从线程 2 中锁定 mutex1,那么该线程当然会被阻塞;这是必须要做的事情。规范中没有说明如果您尝试解锁不属于您的互斥锁会发生什么!
【讨论】:
感谢您的回复。但是当基础说 thread2 无法解锁 thread1 持有的互斥锁时,为什么 PThreads 的实现会有所不同?? @codingfreak:API 不是一件紧身衣。文档是说“不要那样做”,而不是“我们会积极阻止你那样做”。计算机并不总是阻止你做你不应该做的事情。这是一个相当基本的概念,随着您的学习,它会一次又一次地出现:您可以做各种各样的事情,其中许多事情是您不应该做的,并且如果您这样做了,则会有未定义的行为。这就像说“你不能酒后驾车”——没有任何机制积极阻止你这样做,但你仍然不应该这样做。 很遗憾 pthread mutex 使得 Raynal 的读写同步无法实现:en.wikipedia.org/wiki/Readers%E2%80%93writer_lock【参考方案2】:Pthreads 有 3 种不同类型的互斥锁:快速互斥锁、递归互斥锁和错误检查互斥锁。您使用了快速互斥体,出于性能原因,它不会检查此错误。如果你在 Linux 上使用错误检查互斥锁,你会发现你得到了你期望的结果。
下面是您的程序的一个小技巧,作为示例和证明。它将互斥锁锁定在 main() 中,并且创建的线程中的解锁将失败。
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
/*** NOTE THE ATTR INITIALIZER HERE! ***/
pthread_mutex_t mutex1 = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
int counter = 0;
void *functionD(void* data)
int rc;
if ((rc = pthread_mutex_unlock(&mutex1)) != 0)
errno = rc;
perror("other thread unlock result");
exit(1);
pthread_mutex_lock(&mutex1);
counter=10;
printf("Thread02: Counter value: %d\n",counter);
return(data);
int main(int argc, char *argv[])
int rc1;
pthread_t thread1;
if ((rc1 = pthread_mutex_lock(&mutex1)) != 0)
errno = rc1;
perror("main lock result");
if( (rc1 = pthread_create(&thread1, NULL, &functionD, NULL)))
printf("Thread creation failed: %d\n", rc1);
pthread_join(thread1, NULL);
【讨论】:
在 Linux 上使用 -D_GNU_SOURCE 编译。 这应该是公认的答案,更完整!请注意:PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP 不可移植!【参考方案3】:互斥锁用于防止多个线程执行一次只对一个线程安全的代码。
要做到这一点,互斥体有几个特点:
互斥锁可以处理与尝试同时“锁定”互斥锁的多个线程相关的竞争条件,并且始终导致一个线程赢得竞争。
任何失去竞争的线程都会永久进入休眠状态,直到互斥锁被解锁。互斥体维护这些线程的列表。
当互斥锁被刚刚使用它的线程解锁时,A 会将“锁”交给一个且仅一个等待线程。互斥锁将唤醒该线程。
如果这种类型的模式对其他目的有用,那么请继续将其用于其他目的。
回到你的问题。假设您正在使用互斥锁保护某些代码免受多线程访问,假设线程 A 正在执行代码时有 5 个线程正在等待。如果线程 B(不是等待的线程之一,因为它们此时永久处于休眠状态)解锁互斥锁,另一个线程将与线程 A 同时开始执行代码。可能不需要。
也许如果我们知道您对使用互斥锁的想法,我们可以给出更好的答案。您是否在取消线程后尝试解锁互斥锁?您是否有一次可以处理 2 个线程但不能处理 3 个线程的代码,并且没有可以一次允许 2 个线程通过的互斥锁?
【讨论】:
以上是关于Pthread互斥锁由不同的线程解锁的主要内容,如果未能解决你的问题,请参考以下文章