一般来说,
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);
步骤是
pthread_cond_wait(&cond, &mutex);
被调用,它解锁互斥体线程 2 锁定互斥锁并调用
pthread_cond_signal()
,这会解锁互斥锁在线程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 对?
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);
两个线程具有互斥体保护访问的一些共享数据结构。第一个线程想要等到某个条件为真,然后立即执行某些操作(其他线程没有竞争条件机会进入条件检查和操作之间并使条件为假。)第二个线程正在做一些可能会发生的事情。使条件成立,因此它需要唤醒可能正在等待它的任何人。
这是一个典型的示例:线程 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
编辑
正如您在它以原子方式释放互斥锁,并导致调用线程在条件变量 cond 上阻塞;原子地在这里意味着“原子地相对于另一个线程访问互斥体然后访问条件变量”。
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() 函数收到解除阻塞信号时,才会发生线程的锁定和解锁。