我想更好地了解如何使用pthread_cond_wait()
以及它是如何工作的。
我只想对我在本网站上看到的答案进行一些澄清。
答案是本页的最后一条回复
understanding of pthread_cond_wait() and pthread_cond_signal()
我想知道三个线程的外观如何。想象线程1想要告诉线程2和线程3唤醒
例如
pthread_mutex_t mutex;
pthread_cond_t condition;
主题1 :
pthread_mutex_lock(&mutex);
/*Initialize things*/
pthread_mutex_unlock(&mutex);
pthread_cond_signal(&condition); //wake up thread 2 & 3
/*Do other things*/
主题2 :
pthread_mutex_lock(&mutex); //mutex lock
while(!condition){
pthread_cond_wait(&condition, &mutex); //wait for the condition
}
pthread_mutex_unlock(&mutex);
/*Do work*/
主题3 :
pthread_mutex_lock(&mutex); //mutex lock
while(!condition){
pthread_cond_wait(&condition, &mutex); //wait for the condition
}
pthread_mutex_unlock(&mutex);
/*Do work*/
我想知道这样的设置是否有效。假设线程2和3依赖于线程1需要处理的一些初始化选项。
答案 0 :(得分:6)
首先:如果您希望线程#1
唤醒线程#2
和#3
,则应使用pthread_cond_broadcast
。
第二:设置有效(带广播)。线程#2
和#3
被安排用于唤醒,他们将尝试重新获取互斥锁作为唤醒的一部分。其中一个将,另一个将不得不等待互斥锁再次解锁。因此,线程#2
和#3
会连续访问临界区(以重新评估条件)。
答案 1 :(得分:4)
如果我理解正确,你希望thr#2和thr#3(“worker”)阻止直到thr#1(“boss”)执行了一些初始化。
您的方法几乎可行,但您需要广播而不是发出信号,并且缺少与条件变量分开的谓词变量。 (在您引用的问题中,谓词和条件变量的名称非常相似。)例如:
pthread_mutex_t mtx;
pthread_cond_t cv;
int initialized = 0; // our predicate of interest, signaled via cv
...
// boss thread
initialize_things();
pthread_mutex_lock(&mtx);
initialized = 1;
pthread_cond_broadcast(&cv);
pthread_mutex_unlock(&mtx);
...
// worker threads
pthread_mutex_lock(&mtx);
while (! initialized) {
pthread_cond_wait(&cv, &mtx);
}
pthread_mutex_unlock(&mtx);
do_things();
这很常见,您可能希望将mutex / cv / flag组合成单个抽象。 (有关灵感,请参阅Python的Event object。)POSIX barriers这是同步线程的另一种方式:每个线程都等待,直到所有线程都“到达”。 pthread_once
是另一种方式,因为无论有多少线程调用它,它只运行一次函数一次。
答案 2 :(得分:2)
pthread_cond_signal
唤醒等待cond
变量的一个(随机)线程。如果要唤醒等待此cond
变量的所有线程,请使用pthread_cond_broadcast
。
答案 3 :(得分:0)
根据您在关键会议上的工作情况,除了前面的答案中的解决方案之外,还有其他解决方案。
假设thread1
首先执行(即它是创建者线程),并且假设thread2
和thread3
在关键会话中不执行对共享资源的任何写入操作。在这种情况下,使用pthread_cond_wait
会迫使一个线程在实际上不需要时等待另一个线程。
您可以使用pthread_rwlock_t
类型的读写互斥量。基本上thread1
执行写锁定,因此在尝试获取读锁定时其他线程将被阻塞。
此锁的功能非常不言自明:
//They return: 0 if OK, error number on failure
int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock,
const pthread_rwlockattr_t *restrict attr);
int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
thread1
完成初始化后将解锁。其他线程将执行读取锁定,并且由于可以同时存在更多读取锁定,因此它们可以同时执行。再次:如果您不对共享资源在线程2和3中执行任何写操作,则此操作有效。