2012-01-12 208 views
1

我读到互斥体应该被锁定它的同一个线程解锁。让我们考虑下面的情景。pthread互斥锁两个线程互锁锁定/解锁是否有效?

我有一个互斥锁变量说myMuteT1T2两个线程。

  1. T1锁定myMute

  2. T2解锁myMute

  3. T2myMute

  4. T1解锁myMute

这是从不同的线程有序的锁定/解锁有效的方法吗?

+2

不,这违背了互斥体的完整目的,即保护一段代码不被另一段代码打断。正如你阅读它应该只锁定它的代码解锁。这听起来像你有一个不同的问题 - 也许你应该发布实际的问题,并要求正确的解决方案? – 2012-01-12 09:24:29

+0

“应该”是轻描淡写。互斥体只能由当前拥有它的线程解锁。任何尝试通过另一个线程解锁它都会导致潜在的非常危险的未定义行为。 – 2012-01-12 13:43:39

+0

“有效的方法”是什么?你真的想做什么? – 2012-01-13 21:55:21

回答

5

不,这是不正确的。从pthread_mutex_lock手册页:

如果一个线程尝试解除它没有锁定的互斥或互斥这是解锁,导致不确定的行为。

实施例正确排序:

  • T1锁myMutex
  • T2锁myMutex(阻塞等待T1解锁互斥)
  • T1解锁myMutex(T2现在锁定互斥)
  • T2解锁myMutex

编辑:

使用pthread_cond_wait()与误差小例子检查不再赘述:

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <pthread.h> 

volatile int value = 0; 
pthread_mutex_t mymutex; 
pthread_t thread_one; 
pthread_t thread_two; 
pthread_cond_t cond; 

void* main_one(void* ignored) 
{ 
    while (value < 10) 
    { 
     pthread_mutex_lock(&mymutex); 
     pthread_cond_wait(&cond, &mymutex); 
     fprintf(stderr, "T1: value=%d\n", value); 
     pthread_mutex_unlock(&mymutex); 
    } 
    return (void*)0; 
} 

void* main_two(void* ignored) 
{ 
    int i; 

    for (i = 0; i < 10; i++) 
    { 
     pthread_mutex_lock(&mymutex); 
     value++; 
     fprintf(stderr, "T2: value=%d\n", value); 
     pthread_cond_broadcast(&cond); 
     fprintf(stderr, "Broadcasted but T1 cannot continue for 1 second\n"); 
     sleep(1); 
     pthread_mutex_unlock(&mymutex); 
     pthread_yield(); 
    } 

    return (void*)0; 
} 

void start_thread(void* (*a_entry_point)(void*), 
        pthread_t* a_handle) 
{ 
    pthread_attr_t thread_attributes; 

    pthread_attr_init(&thread_attributes); 
    pthread_attr_setdetachstate(&thread_attributes, PTHREAD_CREATE_JOINABLE); 
    pthread_create(a_handle, &thread_attributes, a_entry_point, 0); 
} 

int main() 
{ 
    pthread_mutexattr_t attr; 
    pthread_t thread_one_handle; 
    pthread_t thread_two_handle; 

    /* Init mutex. */ 
    pthread_mutexattr_init(&attr); 
    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK); 
    pthread_mutex_init(&mymutex, &attr); 

    /* Init condition. */ 
    pthread_cond_init(&cond, 0); 

    /* Start threads. */ 
    start_thread(main_one, &thread_one_handle); 
    start_thread(main_two, &thread_two_handle); 

    /* Wait for threads. */ 
    pthread_join(thread_one_handle, 0); 
    pthread_join(thread_two_handle, 0); 

    /* Clean up. */ 
    pthread_cond_destroy(&cond); 
    pthread_mutex_destroy(&mymutex); 

    return 0; 
} 

编译时gcc -Wall -Werror -D_GNU_SOURCE main.c -o main -pthread

+0

1)那么,让我以pthread_cond_wait为例。它会解锁相关的互斥锁,并等待一旦收到信号,然后锁定。 2)。互斥量可用于设置标志,并用信号指示条件变量。 3)。我阅读由Mark,Jeffrey和alex编写的高级linux编程,其中4.4同步和关键会话章节提供了相同的代码。相同的互斥量变量用于设置条件标志,并且相同的互斥量与等待条件变量相关联。我希望我正确地提出了我的问题。:) – Whoami 2012-01-12 09:33:36

+2

必须调用'pthread_cond_wait',并锁定互斥锁,否则会像以前一样调用未定义的行为结果。 – hmjd 2012-01-12 09:49:18

+0

是的,是的,但我指出的是pthread_cond_wait自动解锁互斥锁,然后在等待结束后锁定。在等待改变标志的对象之间可以使用这个相同的互斥对吗?这就是我在问题中提到的场景。 :)。 – Whoami 2012-01-12 09:58:15