理解pthread_cond_wait()和pthread_cond_signal()

use*_*267 36 c++ multithreading mutex

一般来说,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);
Run Code Online (Sandbox Code Playgroud)

步骤是

  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对,它是否可以被许多线程调用?

Chr*_*odd 79

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);
Run Code Online (Sandbox Code Playgroud)

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

  • @ user1944267:线程1将无法重新获取锁(并继续),直到线程2调用pthread_mutex_unlock.但是因为在调用pthread_cond_signal返回后立即发生这种情况,所以会有很少的延迟. (6认同)
  • @ChrisDodd,线程 1 中的一个问题,就在 while 循环之前,我认为我们应该“做一些触发线程 2 的事情”,因为如果线程在线程 1 执行 pthread_wait_cond 之前是触发器,则信号丢失,线程 1 将处于无限状态等待 (2认同)

Lud*_*dzu 7

这是一个典型的例子:线程1正在等待一个条件,这可以由线程2来完成.

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

pthread_mutex_t mutex;
pthread_cond_t condition;
Run Code Online (Sandbox Code Playgroud)

线程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);
Run Code Online (Sandbox Code Playgroud)

线程2:

pthread_mutex_lock(&mutex);

/* do something that may fulfill the condition */

pthread_mutex_unlock(&mutex);
pthread_cond_signal(&condition); //wake up thread 1
Run Code Online (Sandbox Code Playgroud)

编辑

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

它自动释放互斥锁并导致调用线程阻塞条件变量cond; 原子地这里的意思是"相对于另一个线程访问互斥锁然后条件变量的原子性".

  • 诀窍是,在线程 1 中,pthread_cond_wait 暂时释放互斥锁。 (3认同)