70

一般而言,pthread_cond_wait()并被pthread_cond_signal()称为如下:

//thread 1:
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond, &mutex);
do_something()
pthread_mutex_unlock(&mutex);

//thread 2:
pthread_mutex_lock(&mutex);
pthread_cond_signal(&cond);  
pthread_mutex_unlock(&mutex);

步骤是

  1. pthread_cond_wait(&cond, &mutex);被调用,它解锁互斥锁

  2. 线程 2 锁定互斥体并调用pthread_cond_signal(),从而解锁互斥体

  3. 在线程 1 中,pthread_cond_wait()再次调用并锁定互斥锁

现在在线程 2 中,在pthread_cond_signal()被调用 之后pthread_mutex_unlock(&mutex),它将运行,在我看来,它想要解锁一个现在被线程 1 锁定的互斥锁。我的理解有什么问题吗?

此外,在我看来,pthread_cond_wait()同一 cond-mutex 对只能由 1 个线程调用。但是有一种说法“pthread_cond_signal() 函数应至少解除阻塞在指定条件变量 cond 上阻塞的线程之一(如果任何线程在 cond 上阻塞)。” 那么,这意味着pthread_cond_wait()可以由多个线程为同一个 cond-mutex 对调用吗?

4

3 回答 3

124

pthread_cond_signal不解锁互斥锁(它不能因为它没有引用互斥锁,所以它怎么知道要解锁什么?)事实上,信号不需要与互斥锁有任何连接;信号线程不需要持有互斥锁,但对于大多数基于条件变量的算法来说,它会持有。

pthread_cond_wait就在它睡觉之前解锁互斥锁(正如你注意到的那样),但是当它发出信号时,它会在它唤醒之前重新获取互斥锁(这可能需要等待)。因此,如果信号线程持有互斥锁(通常情况下),等待线程将不会继续,直到信号线程也解锁互斥锁。

条件变量的常见用法如下:

thread 1:
    pthread_mutex_lock(&mutex);
    while (!condition)
        pthread_cond_wait(&cond, &mutex);
    /* do something that requires holding the mutex and condition is true */
    pthread_mutex_unlock(&mutex);

thread2:
    pthread_mutex_lock(&mutex);
    /* do something that might make condition true */
    pthread_cond_signal(&cond);
    pthread_mutex_unlock(&mutex);

这两个线程有​​一些共享数据结构,互斥锁正在保护对这些数据结构的访问。第一个线程想要等到某个条件为真,然后立即执行某些操作(没有竞争条件机会让其他线程进入条件检查和操作之间并使条件为假。)第二个线程正在做一些可能使条件为真,因此它需要唤醒任何可能正在等待它的人。

于 2013-05-13T14:10:10.000 回答
12

这是一个典型的例子:线程 1 正在等待一个条件,该条件可能由线程 2 满足

我们使用一个互斥锁和一个条件。

pthread_mutex_t mutex;
pthread_cond_t condition;

线程 1:

pthread_mutex_lock(&mutex); //mutex lock
while(!condition){
    pthread_cond_wait(&condition, &mutex); //wait for the condition
}

/* do what you want */

pthread_mutex_unlock(&mutex);

线程2:

pthread_mutex_lock(&mutex);

/* do something that may fulfill the condition */

pthread_mutex_unlock(&mutex);
pthread_cond_signal(&condition); //wake up thread 1

编辑

正如您在pthread_cond_wait手册中看到的那样:

它以原子方式释放互斥锁并导致调用线程阻塞条件变量 cond;atomically 这里的意思是“原子地相对于另一个线程访问互斥锁,然后是条件变量”。

于 2013-05-13T14:42:50.420 回答
1

我从这里举例说明 https://www.geeksforgeeks.org/condition-wait-signal-multi-threading/

并修改为此,

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

// Declaration of thread condition variable 
pthread_cond_t cond = PTHREAD_COND_INITIALIZER; 

// declaring mutex 
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; 

// Thread function 
void releaseFun() 
{ 
    // Let's signal condition variable cond
    printf("Signaling condition variable cond\n"); 
    pthread_cond_signal(&cond); 
}

// Thread function 
void* blockedThread() 
{
    // acquire a lock 
    pthread_mutex_lock(&lock); 
    printf("Waiting on condition variable cond\n");
    pthread_cond_wait(&cond, &lock); 
    // release lock 
    pthread_mutex_unlock(&lock); 

    printf("Returning thread\n"); 

    return NULL; 
}    

// Driver code 
int main() 
{ 
    pthread_t tid;

    // Create thread 1 
    pthread_create(&tid, NULL, blockedThread, NULL); 

    // sleep for 1 sec so that thread 1 
    // would get a chance to run first 
    sleep(1); 

    releaseFun();
    // wait for the completion of thread 2 
    pthread_join(tid, NULL); 

    return 0; 
}

输出:gcc test_thread.c -lpthread

等待条件变量 cond

信号条件变量 cond

返回线程

只有当 blockThread 的 pthread_cond_wait() 函数被通知解除阻塞时,才会发生线程的锁定和解锁。

于 2020-09-16T08:43:14.490 回答