pthread_cond_wait()同时唤醒两个线程

时间:2015-07-15 21:04:43

标签: c multithreading pthreads

我想更好地了解如何使用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需要处理的一些初始化选项。

4 个答案:

答案 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首先执行(即它是创建者线程),并且假设thread2thread3在关键会话中不执行对共享资源的任何写入操作。在这种情况下,使用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中执行任何写操作,则此操作有效。