天真的问题..
我在说之前读过 - “只有锁定它的线程才能解锁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);
}
答案 0 :(得分:21)
Pthreads有3种不同的互斥锁:快速互斥锁,递归互斥锁和错误检查互斥锁。您使用了一个快速互斥锁,出于性能原因,它不会检查此错误。如果你在Linux上使用错误检查mutex,你会发现你得到了你期望的结果。
以下是您的程序的一个小黑客作为示例和证明。它锁定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);
}
答案 1 :(得分:19)
您所做的事情根本就不合法,行为未定义。互斥锁仅排除规则播放的线程。如果你试图从线程2锁定mutex1,那么线程当然会被阻塞;这是必需的事情。规范中没有任何内容说明如果您尝试解锁不属于您的互斥锁会发生什么!
答案 2 :(得分:-2)
互斥锁用于防止多个线程执行一次只对一个线程安全的代码。
要做到这一点,互斥锁有几个功能:
互斥锁可以处理与多个线程相关联的竞争条件,这些线程试图同时“锁定”互斥锁,并且总是会有一个线程赢得比赛。
任何失去比赛的线程都会永久地进入睡眠状态,直到互斥锁解锁为止。互斥锁维护着这些线程的列表。
当正在使用互斥锁的线程解锁互斥锁时,A会将“锁定”交给一个且只有一个等待线程。互斥锁将唤醒该线程。
如果这种类型的模式对某些其他目的有用,那么请继续使用它,原因不同。
回到你的问题。假设您使用互斥锁保护多个线程访问的某些代码,并且假设5个线程正在等待,而线程A正在执行代码。如果线程B(不是其中一个等待,因为它们暂时处于休眠状态)解锁互斥锁,另一个线程将开始执行与线程A同时的代码。可能不需要。
也许如果我们知道你在使用互斥锁的想法,我们可以给出更好的答案。您是否尝试在线程取消后解锁互斥锁?您是否拥有一次可以处理2个线程但不能处理3个线程的代码,并且没有可以同时处理2个线程的互斥锁?