根据POSIX,
破坏当前没有线程被阻塞的初始化条件变量应该是安全的。
此外,指定信号和广播操作以解除对条件变量上阻塞的一个/所有线程的阻塞。
因此,在我看来,以下形式的自同步破坏应该是有效的,即呼叫pthread_cond_destroy
:
当然,假设没有其他服务员到达,之后不再执行任何信号,如果使用pthread_cond_destroy
,应用程序负责保证。
我是否认为在这些情况下销毁是有效的?还有其他自我同步的破坏场景需要注意条件变量吗?
最后,对于进程共享的cond变量,在没有破坏的情况下取消映射共享映射可能是有意义的,期望取消映射在相同的上下文中有效是合理的,破坏是有效的,或者如果多个线程中必须进行进一步的同步相同的进程(地址空间)使用相同的映射,并希望在上述某个上下文中取消映射?
答案 0 :(得分:2)
不,我不认为你的大部分假设都是正确的。从pthread_cond_signal
或pthread_cond_broadcast
返回并不表示任何线程尚未从条件变量“解除阻塞”,即要解除阻塞的线程不再需要访问该变量。该标准仅表示“应解锁”,而不是“在通过此呼叫成功返回时,它们将被解锁”。后者对于实现来说是非常严格的限制,所以可能有一个很好的理由就是按原样制定它。
所以我认为从您描述的场景中只有一个是有效的,即案例是被单独阻塞的线程或进程在被唤醒后破坏了该条件。
答案 1 :(得分:0)
虽然我同意您对此语言的解释(以及Open POSIX测试套件的解释),但使用依赖于实现。因此,这里是一些主要实现的快速概述:
pthread_cond_destroy()
将返回EBUSY
,如果有条件仍然阻止线程。销毁责任将传递给未解锁信号的线程。pthread_cond_destroy()
将返回EBUSY
如果有条件仍然阻止线程。发出信号但未解除阻塞的线程将在pthread_cond_destroy()
将控制权返回给应用程序之前执行。pthread_cond_destroy()
将返回EBUSY
如果有条件仍然阻止线程。没有为阻塞但发出信号的线程做出规定。pthread_cond_destroy()
如果条件仍然被阻止,则会返回EBUSY
。没有为阻塞但发出信号的线程做出规定。__futex_wake_ex
的系统实施是否同步。因此pthread_cond_broadcast()
必须阻塞,直到所有线程都被唤醒(但没有释放它们的互斥锁)。PulseEvent()
函数来实现pthread_cond_broadcast()
。这有一个known race condition EINVAL
,则返回pthread_cond_destroy()
<强> 修改 强>
主要问题是,如果我正确阅读了您的评论,pthread_cond_wait()
是否可以在返回之前访问条件变量,但之后是否已取消阻止。答案是是。该例程假定其参数将保持有效。
这意味着在广播之后,您的线程不能假设条件变量未被其他线程使用。
当您致电pthread_cond_broadcast()
时,您无法获取相关的互斥锁。等待条件变量的线程将按顺序执行,而每个线程都会串行获取相关的互斥锁。因为您的服务员可能会互相阻止,所以您的广播线程可能会继续执行,而服务员仍然在互联网上pthread_cond_wait()
被阻止(但不等待该条件)。
编辑2
[...]期望取消映射在相同的上下文中有效是否合理?销毁是否有效?
我不认为这是基于编辑1中的推理的合理期望。如果您被禁止使用pthread_cond_destroy()
答案 2 :(得分:0)
评论(不回答):
这是你的想法吗?
全局:
// protected by m: pthread_mutex_t m; pthread_cond_t c; bool about_to_pthread_cond_wait = false; bool condition_waited_on = false;
主题A:
pthread_mutex_lock (&m); { // locked region about_to_pthread_cond_wait = true; while (condition_waited_on) { // pthread_cond_wait (&m, &c) is decomposed here: __pthread_mutex_cond_wait_then_unlock (&m, &c); // unlocked region pthread_mutex_lock (&m); } } pthread_mutex_unlock (&m);
主题B:
for (bool break_loop = false; !break_loop;) { pthread_mutex_lock (&m); { // locked region condition_waited_on = true; if (about_to_pthread_cond_wait) { pthread_cond_signal (&c); pthread_cond_destroy (&c); break_loop = true; } } pthread_mutex_unlock (&m); pthread_yield (); }
编辑:
我认为pthread_cond_wait (&m, &c);
会这样做:
__pthread_mutex_cond_wait_then_unlock (&m, &c); pthread_mutex_lock (&m);
__pthread_mutex_cond_wait_then_unlock
将监控CV的信号,然后解锁互斥锁,然后进入睡眠状态。
如果简历中有__pthread_mutex_cond_wait_then_unlock
和pthread_cond_signal
必须锁定的内部互斥锁,那么我认为__pthread_mutex_cond_wait_then_unlock
会这样做:
pthread_mutex_lock (&c.int_mutex); { // locked region for c.int_state __register_wakeup_cond (&c.int_state); pthread_mutex_unlock (&m); } pthread_mutex_unlock (&c.int_mutex); // will not touch c.int_state any more __sleep_until_registered_wakeups ();
和pthread_cond_signal
确实:
pthread_mutex_lock (&c.int_mutex); { // locked region for CV internal state __wakeup_registered (&c.int_state); } pthread_mutex_unlock (&c.int_mutex);
然后只有在pthread_cond_destroy
使用__pthread_mutex_cond_wait_then_unlock
后才会调用c.int_state
。