2011-03-28 92 views
13

幼稚的问题Pthread互斥锁解开..不同线程

我说之前阅读 - “一个互斥,必须由锁定它的线程只能解锁

但我已经写一个程序,其中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

@Santiago - 添加了示例代码.. – codingfreak 2011-03-28 04:53:16

+0

不 - 但SEMAPHORE的值为1可以像互斥体一样,并且可以从不同的线程解锁。但是,您可能需要使用互斥锁来保护信号量的运算,以使其值停留在1以上。 – aaa90210 2017-04-02 04:30:42

回答

17

你做了什么,根本就不是合法的,行为是不确定的。互斥体仅排除按规则播放的线程。如果你试图从线程2中锁定互斥体1,那么线程当然会被阻塞;这是要做的事情。规范中没有任何内容说明如果您尝试解锁您不属于自己的互斥锁,会发生什么情况!

+0

感谢您的回复。但是当基础知识说thread2不能解锁thread1持有的互斥体时,为什么PThreads的实现不同? – codingfreak 2011-03-28 05:01:35

+24

@codingfreak:API不是一件紧身衣。文件说“不要那样做”,而不是“我们会积极阻止你这样做”。电脑并不总是阻止你做你不应该做的事情。这是一个相当基本的概念,随着你的学习会一次又一次地出现:你可以做各种各样的事情,其中​​许多事情你不应该做,而且如果你这样做的话会有不确定的行为。这就像是说“你不能开车喝醉酒” - 没有任何机制可以阻止你这样做,但你仍然不应该这样做。 – 2011-03-28 05:06:06

+0

+1给你们两个,伙计们。好的解释! – slezica 2011-03-28 05:58:08

19

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); 
} 
+3

在Linux上使用-D_GNU_SOURCE编译。 – Lupus 2014-09-11 09:09:18

-2

互斥锁用于防止多线程执行一次只对一个线程安全的代码。

为此互斥有几个特点:

  1. 互斥可以处理多个线程试图“锁定”在同一时间互斥锁,并总是相关联的比赛条件有一个线程获胜的结果种族。

  2. 任何失去竞赛的线程都会永久睡眠,直到互斥锁被解锁。互斥体维护这些线程的列表。

  3. 当正在使用它的线程解锁互斥锁时,A将把“锁”交给一个且仅有的一个等待线程。互斥体将唤醒该线程。

如果这种类型的模式对其他目的有用,那么请继续使用它,原因不同。

回到你的问题。假设你用一个互斥体来保护一些代码免受多个线程访问,并且让5个线程在线程A执行代码时等待。如果线程B(不是等待,因为它们现在永久睡眠)解锁互斥体,另一个线程将开始与线程A同时执行代码。可能不需要。

也许如果我们知道你在考虑使用互斥锁,我们可以给出更好的答案。在线程被取消后你是否试图解锁互斥锁?你有一次可以处理2个线程的代码,但不是三个,并且没有互斥体让一次2个线程通过?