根据cppreference, std :: atomic< t> t> )
将通知 至少 一个正在等待所述原子的线程。这意味着,根据标准,它可以解开多个线程。这与 ,它指定它将解开(不超过)一个线程。
这种差异从何而来?这不使用相同的基本机制吗?就标准库的实现而言,所有流行的库是否都有机会实际上可以对此呼叫进行覆盖,或者是否有一些完全没有阻止一个?
According to cppreference, std::atomic<T>::notify_one()
will notify at least one thread that is waiting on said atomic. This means that according to the standard it could unblock more than one thread. This is in contrast to std::condition_variable::notify_one()
, which specifies that it will unblock (no more than) one thread.
Where does this difference come from? Does this not use the same underlying mechanism? As far as implementations of the standard library go, do all of the prevalent ones have a chance of actually unblocking multiple with this call, or are there some that always unblock exactly one?
发布评论
评论(2)
两者都
std
和
std ::
允许随时伪造,包括在
notify_one
的特定时间。因此,就规范而言,尽管确实确实看来该标准对两个使用不同的措辞(“ 至少一个” [atomics.types.operation]/32 ,但只是 [thread.condition.condition.condition.condvar]/5 ),我没有认为这里有任何规范上的差异。当调用
notify_one
时,只要它至少是一个(如果有等待的话),则可以自由地解开两个等待操作的任何数量的线程。对于std :: atomic :: notify_one
以及std :: preengation_variable :: notify_one_one
(即“不超过)) “是错误的)。在较早的修订中,该提案对于
std :: Atomic
等待操作仍然说“ 一个”,而不是“ 至少一个”。修订版 >,根据哪些措辞改进,部分是根据LWG电视会议的反馈。我认为这些电视会议的任何文档都没有公开可用,因此我无法判断这种措辞更改是否有特定意图。
也许应该避免误解,因为在不同的段落中提到了虚假的解密,或者可能是为了表达有一些实现的实现,这些实施可以解除多个/所有等待操作,这些操作是专门为支持的。另请参阅问题和此答案下的评论。
Both
std::atomic::wait
andstd::condition_variable::wait
are allowed to unblock spuriously at any time, including at the specific time thatnotify_one
is called.So in terms of the specification, although it does indeed seem that the standard uses different wording for the two ("at least one" in [atomics.types.operation]/32 but just "one" in [thread.condition.condvar]/5), I don't think there is any normative difference here. The implementation is free to unblock any number of threads for both waiting operations when
notify_one
is called, as long as it is at least one (if any are waiting). This is true forstd::atomic::notify_one
as well asstd::condition_variable::notify_one
(i.e. "(no more than)" is wrong).In an earlier revision of the proposal [P1135R4] for the
std::atomic
waiting operations it still said "one" instead of "at least one" in the proposed wording.That was changed with revision [P1135R5], according to which wording improvements were made partly in response to feedback from LWG teleconferences. I don't think any documentation of these teleconferences is publicly available, so I can't tell whether there was a specific intent in this wording change.
Maybe it is supposed to avoid misunderstandings since the spurious unblocking is mentioned in a different paragraph or maybe it is meant to convey that there are implementations which do unblock multiple/all waiting operations that are specifically intended to be supported as such. See also comments under the question and this answer.
据我所知,他们可以使用相同的机制,但不必这样做。我通常使用的实现是libstdc ++,其原子:: notify_one()绝对不同。
条件_variable相当不透明,在bits/std_mutex.h标题中以__condvar的形式实现。它的只需调用pthread包装器:
而notify_all()而不是调用__gthread_cond_broadcast。
这与原子学形成鲜明对比,这些原子的参与得多,但最终使用一系列函数来通知线程,从 __ atomic_notify_address :
__ waiter_base :: _ m_notify :
__ waiter_pool_base :: _ m_notify :: _ m_notify
只需使用条件变量通知一个或所有线程即可。否则,它是使用futex实现的,并且也可能唤醒(最多? v3/inclage/bits/atomic_wait.h#l119“ rel =“ noreferrer”> __ platform_notify :
As far as I can tell, they can use the same mechanism, but don't have to. The implementation I typically use is libstdc++ and its atomic::notify_one() is definitely different.
The condition_variable is fairly opaque, implemented as __condvar in the bits/std_mutex.h header. Its notify_one() just calls a pthread wrapper:
whereas notify_all() instead calls __gthread_cond_broadcast.
This contrasts with the atomics, which are much more involved, but end up using a sequence of functions for notifying threads, starting with __atomic_notify_address:
__waiter_base::_M_notify:
__waiter_pool_base::_M_notify:
So if there is no _GLIBCXX_HAVE_PLATFORM_WAIT, libstdc++ will simply use a condition variable to notify either one or all threads. Otherwise, it's implemented using a futex, and may also wake (up to?) INT_MAX threads, see __platform_notify: