【问题标题】:Guaranteeing execution of pthread_cond_wait before pthread_wait_signal保证 pthread_cond_wait 在 pthread_wait_signal 之前执行
【发布时间】:2013-07-12 03:24:01
【问题描述】:

不确定这个问题之前是否被问过,但它如何(或是否)保证pthread_cond_waitpthread_cond_signal/broadcast 之前执行?

如果在随后的pthread_cond_signal 被调用之后一个线程调用pthread_cond_wait 会发生什么?

信号会丢失吗?

如果pthread_cond_signal 是一个阻塞调用(从描述“至少一个线程被唤醒”中听上去像是这样),那么处于阻塞状态的互斥体会发生什么情况?谢谢您的帮助!

【问题讨论】:

  • 另外,pthread_cond_broadcast 是如何执行的?调用线程是否被阻塞,直到所有等待该条件的线程都被唤醒?
  • 没有。 pthread_cond_signalpthread_cond_broadcast 都不会阻止他们的来电者。
  • 另一个问题,那么调用 pthread_cond_signal 会立即唤醒等待的线程吗?等待函数的描述说,当等待函数返回时,互斥锁再次归等待线程所有。那么现在信号线程不是同时拥有互斥锁吗?
  • pthread_cond_wait 在重新获取互斥体之前无法返回。如果信令线程在发信号时持有互斥锁,那么它可以通过释放互斥锁来控制服务员何时能够“唤醒”。如果它在发出信号之前已经释放了互斥锁,那么它就无法控制服务员的唤醒;只要没有其他线程占用互斥锁,服务员就可以在信号发出后立即唤醒。
  • 太棒了!这解释了很多。谢谢你的帮助。欣赏它。

标签: c++ c pthreads


【解决方案1】:

pthread_cond_wait 发生在pthread_cond_signal 之前或之后都没有关系,因为你只在谓词为 false 时调用pthread_cond_wait,并且谓词所依赖的状态不能改变,而与条件变量关联的互斥锁举行。

假设服务员正在做类似的事情:

pthread_mutex_lock(mutex);
while (!predicate(state)) pthread_cond_wait(cond, mutex);
pthread_mutex_unlock(mutex);

为了有理由向条件变量发出信号,执行信号的线程必须对state 进行一些更改。为了在不调用未定义行为的情况下执行此操作,它必须持有mutex,它保护state。但是,这意味着对state 的更改之前完成了上述代码 sn-p(在这种情况下,pthread_cond_wait 永远不会被调用,因为predicate(state) 现在为真),在调用@期间987654331@(互斥锁解锁时;在这种情况下,更改state后的信号将解除等待),或者在上述代码sn-p结束后(在这种情况下无关)。

【讨论】:

  • 明白了。所以状态也受到同一个互斥锁的保护。所以看起来你使用 cond_wait 的唯一原因是避免连续轮询谓词的状态和占用 cpu 周期。感谢您的回答!
  • 这不仅仅是为了避免占用 cpu 周期,而是让修改状态的线程有机会运行。您可以“连续轮询”的唯一方法是快速锁定和解锁互斥锁,如果运气不好,想要更改状态的线程可能永远无法获得互斥锁。
  • 那么这就引出了另一个问题,当多个线程在相同条件下等待并且正在使用广播时会发生什么?我在这里猜测那些线程被一一唤醒。那么如果谓词在我们唤醒线程的过程中改变了状态会发生什么呢?程序员有责任不让这种情况发生吗?在那种情况下,他怎么知道广播过程已经完成,现在可以安全地更改谓词的状态了。
  • 我猜每次使用不同的条件变量就可以解决这个问题。
  • 我认为你在想象不存在的问题。仅当您持有保护它的互斥锁时,更改谓词所依赖的状态是安全的,因为当您持有互斥锁时,没有其他线程可以检查或更改它。 (这当然是假设您正确使用了互斥锁。)
猜你喜欢
  • 2019-03-09
  • 2010-11-16
  • 1970-01-01
  • 1970-01-01
  • 2019-09-04
  • 2013-10-15
  • 2015-03-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多