什么时候可以使用 cond var 来同步其自身的销毁/取消映射?
根据 POSIX 的规定,
销毁当前没有线程被阻塞的已初始化条件变量应该是安全的。
此外,信号和广播操作被指定为解除阻塞在条件变量上阻塞的一个/所有线程。
因此,在我看来,以下形式的自同步销毁应该是有效的,即调用pthread_cond_destroy:
- 在成功发出信号后,在等待线程或信号线程中,当恰好一个线程被阻塞时在条件变量上。
- 成功广播后,在任何等待线程或广播线程中立即进行。
当然,这假设不会有更多的等待者到达,并且之后不会执行更多的信号,如果使用 pthread_cond_destroy,应用程序负责保证这一点。
我认为在这些情况下破坏是有效的,对吗?是否还有其他需要注意条件变量的自同步破坏场景?
最后,对于进程共享条件变量,在不破坏的情况下取消映射共享映射可能有意义,期望取消映射在相同上下文中有效是否合理,破坏将有效,或者如果同一进程中的多个线程必须执行进一步同步(地址空间)正在使用相同的映射并希望在上述上下文之一中取消映射?
According to POSIX,
It shall be safe to destroy an initialized condition variable upon which no threads are currently blocked.
Further, the signal and broadcast operations are specified to unblock one/all threads blocked on the condition variable.
Thus, it seems to me the following forms of self-synchronized destruction should be valid, i.e. calling pthread_cond_destroy
:
- Immediately after a successful signal, in either the waiting or the signaling thread, when exactly one thread is blocked on the cond var.
- Immediately after a successful broadcast, in either any waiting thread or the broadcasting thread.
Of course this assumes no further waiters will arrive and no further signals shall be performed afterwards, which the application is responsible for guaranteeing if using pthread_cond_destroy
.
Am I correct that destruction is valid in these situations? And are there other self-synchronized destruction scenarios to be aware of with condition variables?
Finally, for process-shared cond vars where unmapping the shared mapping without destruction might make sense, is it reasonable to expect unmapping to be valid in the same contexts destruction would be valid, or must further synchronization be performed if multiple threads in the same process (address space) are using the same mapping and want to unmap it in one of the above contexts?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
不,我不认为你的大多数假设都是正确的。从
pthread_cond_signal
或pthread_cond_broadcast
返回并不表示任何线程尚未从条件变量中“解除阻塞”,即要解除阻塞的线程不需要不再访问该变量。该标准只说“应解锁”,而不是“从该调用成功返回后,它们将被解锁”。后者对于实现来说会受到很大的限制,因此按原样制定可能是有充分理由的。因此,我认为从您描述的场景来看,只有一种情况是有效的,即单独阻塞的线程或进程在被唤醒后破坏条件的情况。
No, I don't think that most of your assumptions are correct. Returning from
pthread_cond_signal
orpthread_cond_broadcast
does not indicate that any of the threads are yet "unblocked" from the condition variable, i.e that the threads that are to be unblocked don't need access to that variable anymore. The standard only says "shall unblock" and not "on successful return from this call they will be unblocked". The later would be very restrictive for implementations, so there is probably a good reason that this is formulated as it is.So I think from the scenarios you describe only one is valid, namely the case were the solely blocked thread or process destroys the condition after being woken up.
评论(不是回答):
这是你的想法吗?
全局:
线程 A :
线程 B:
编辑:
我假设
pthread_cond_wait (&m, &c);
确实:__pthread_mutex_cond_wait_then_unlock
将监视到 CV 的信号,然后解锁互斥体,然后进入睡眠状态。如果 CV 有一个内部互斥锁,
__pthread_mutex_cond_wait_then_unlock
和pthread_cond_signal
必须锁定内部,那么我假设__pthread_mutex_cond_wait_then_unlock
会这样做:并且
pthread_cond_signal
> 确实:那么
pthread_cond_destroy
只会是在__pthread_mutex_cond_wait_then_unlock
使用完c.int_state
后调用。Comment (not answer):
Is that what you have in mind?
Global:
Thread A :
Thread B:
EDIT:
I assume
pthread_cond_wait (&m, &c);
does:__pthread_mutex_cond_wait_then_unlock
will being monitoring the signals to the CV, then unlock the mutex, then go to sleep.If the CV has an internal mutex that
__pthread_mutex_cond_wait_then_unlock
andpthread_cond_signal
must lock internaly, then I assume__pthread_mutex_cond_wait_then_unlock
does:and
pthread_cond_signal
does:Then
pthread_cond_destroy
will only be called after__pthread_mutex_cond_wait_then_unlock
has finished usingc.int_state
.虽然我同意您对此语言的解释(以及 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()
。这有一个已知的竞争条件Oddballs
pthread_cond_destroy()
,则返回EINVAL
编辑
如果我正确地阅读了您的评论,主要问题是
pthread_cond_wait()
是否可以之前访问条件变量 它返回,但之后它被解锁。答案是是。该例程假定其参数仍然有效。这意味着在广播之后,您的线程不能假设条件变量未被其他线程使用。
当您调用
pthread_cond_broadcast()
时,您不会获取关联的互斥锁。当等待条件变量的线程将按顺序执行时,每个线程都会串行获取关联的互斥体。由于您的等待者可能会互相阻塞,因此您的广播线程可能会继续执行,而等待者仍处于互斥锁上的pthread_cond_wait()
阻塞状态(但不等待条件)。编辑 2
根据编辑 1 中的推理,我认为这不是一个合理的期望。如果您无法使用
pthread_cond_destroy()
,则肯定需要额外的同步While I agree with your interpretation (and that of the Open POSIX test suite) of this language, usage will be implementation dependent. As such, here is a quick rundown of some of the major implementations:
Safe
pthread_cond_destroy()
will returnEBUSY
if there are threads still blocked on the condition. Destruction responsibility will pass to the threads that are signaled by not unblocked.pthread_cond_destroy()
will returnEBUSY
if there are threads still blocked on the condition. Threads that are signaled but not unblocked will be executed beforepthread_cond_destroy()
returns control to the application.Safe but blocking
pthread_cond_destroy()
will returnEBUSY
if there are threads still blocked on the condition. No provisions are made for blocked but signaled threads.pthread_cond_destroy()
will returnEBUSY
if there are threads still blocked on the condition. No provisions are made for blocked but signaled threads.Possibly not safe
__futex_wake_ex
to be synchronous. Thuspthread_cond_broadcast()
must block until all threads have woken (but not released their mutex).PulseEvent()
function to implementpthread_cond_broadcast()
. This has a known race conditionOddballs
EINVAL
ifpthread_cond_destroy()
is called on a condition variable that is still referencedEdit
The major issue, if I read your comments correctly is whether the
pthread_cond_wait()
can access the condition variable before it returns but after it is unblocked. And the answer is yes. The routine assumes that its arguments will remain valid.This means that after broadcasting, your thread cannot assume that the condition variable is unused by other threads.
When you call
pthread_cond_broadcast()
, you do not acquire the associated mutex lock. While the threads waiting on your condition variable will execute sequentially, each acquiring the associated mutex in series. Because your waiters may block each other, your broadcasting thread may continue executing while waiters are still inpthread_cond_wait()
blocked on the mutex (but not waiting for the condition).Edit 2
I don't think that this is a reasonable expectation based on the reasoning in Edit 1. Additional synchronization would definitely be required if you are precluded from using
pthread_cond_destroy()