【问题标题】:Must lock be held when signaling conditional variable?发出条件变量信号时必须保持锁定吗?
【发布时间】:2020-03-01 04:34:25
【问题描述】:

好的。这里的例子是使用 c 中的 pthread lib 提供的。

在教科书中我遇到了以下代码:

//for thread 2
pthread_mutex_lock(&lock);
should_wake_up = 1;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&lock);

这段代码运行良好。我只是想知道以下代码是否也有效?

//for thread 2
pthread_mutex_lock(&lock);
should_wake_up = 1;
pthread_mutex_unlock(&lock);
pthread_cond_signal(&cond);//signal the conditional variable but the lock is not held

以下代码的优缺点是什么?

PS。假设合作线程有代码:

//for thread 1
pthread_mutex_lock(&lock);
while(!should_wake_up)
    pthread_cond_wait(&cond, &lock);
pthead_mutex_unlock(&lock);

PS2。我遇到了一些其他问题,它指出如果我们不希望信号丢失,我们必须使用锁来确保关联的谓词(在本例中为 should_wake_up)在锁定时不能更改线程1。在这种情况下,这似乎不是问题。帖子链接:[1]:signal on condition variable without holding lock。我认为他的问题是他忘记了锁定。但我的问题不同。

【问题讨论】:

  • 每次提出这个问题时,正确解释问题的人和根本误解问题的人之间都会展开激烈的辩论。您需要在*_wait()-ing 任务和*_signal()-ing 任务之间有一个共享谓词,并且此状态必须由互斥体保护,因为它是从多个线程并发访问的。 condvar 本身也必须受到互斥体的保护。互斥体(互斥体?)必须相同。因此,signal()-er 必须在修改共享状态之前 aqcuired 互斥体。它不再需要持有锁。

标签: multithreading pthreads


【解决方案1】:

对于正常使用,您可以在发出条件变量信号之前解锁互斥锁。

互斥锁保护共享状态(在本例中为should_wake_up 标志)。如果在修改共享状态时互斥锁被锁定,并且在检查共享状态时,可以在互斥锁不锁定的情况下调用pthread_cond_signal,一切都会按预期工作。

在大多数情况下,我会建议调用pthread_cond_signal 调用pthread_mutex_unlock 后调用pthread_mutex_unlock 作为性能的轻微改进。如果您在pthread_mutex_unlock 之前调用pthread_cond_signal,则等待线程可以在互斥锁解锁之前被信号唤醒,因此等待线程必须重新进入睡眠状态,因为它阻塞了仍然由信号线程。

【讨论】:

  • 我认为如果你先解锁,那么其他线程可能会抓住锁并导致虚假唤醒。
猜你喜欢
  • 2021-10-21
  • 2014-02-21
  • 1970-01-01
  • 2013-01-24
  • 2016-11-10
  • 1970-01-01
  • 2015-07-08
  • 2013-12-17
  • 2011-07-07
相关资源
最近更新 更多