pthread_cond_wait()和pthread_cond_signal()的理解

问题描述 投票:0回答:3

一般来说,

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锁定的互斥锁。我的理解有什么问题吗?

此外,在我看来,对于同一个 cond-mutex 对,只能由 1 个线程调用

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

c multithreading pthreads mutex condition-variable
3个回答
140
投票

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

pthread_cond_wait
在互斥体休眠之前解锁(正如您所注意到的),但是当它收到信号时,它会在唤醒之前重新获取互斥体(这可能需要等待)。因此,如果信号线程持有互斥锁(通常情况),等待线程将不会继续,直到信号线程也解锁互斥锁。

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

thread1:
    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);

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


14
投票

这是一个典型的示例:线程 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 上阻塞;原子地在这里意味着“原子地相对于另一个线程访问互斥体然后访问条件变量”。


0
投票
我从这里举了例子

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() 函数收到解除阻塞信号时,才会发生线程的锁定和解锁。

© www.soinside.com 2019 - 2024. All rights reserved.