![](/img/trans.png)
[英]Why std::call_once behave different in joined and detached threads?
[英]Is notification of threads guaranteed for std::call_once after exceptional call
cppreference.com上std::call_once
的标准示例描述了异常调用的行为,这是我理解的其他线程等待第一次进入std::call_once
,如果是异常,下一个线程将尝试执行std::call_once
。 虽然在线编译器确认了这种行为,但我无法在本地重现它。 对于最小的例子
#include <iostream>
#include <thread>
#include <mutex>
std::once_flag flag;
void may_throw_function(bool do_throw)
{
if (do_throw) {
std::cout << "throw: call_once will retry\n";
throw std::exception();
}
std::cout << "Didn't throw, call_once will not attempt again\n";
}
void do_once(bool do_throw)
{
try {
std::call_once(flag, may_throw_function, do_throw);
}
catch (...) {}
}
int main()
{
std::thread t1(do_once, true);
std::thread t2(do_once, true);
std::thread t3(do_once, false);
std::thread t4(do_once, true);
t1.join();
t2.join();
t3.join();
t4.join();
}
从cppreference.com复制后,执行在第一次投掷后被卡住并永远运行
编译使用g++-5 -std=c++14 source.cpp -pthread
(版本g++ (Ubuntu 5.4.0-6ubuntu1~16.04.11) 5.4.0 20160609
)或clang++-6.0 source.cpp -pthread
(版本) clang version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final)
)。
将更多输出放入代码中会显示所有线程都已启动,但只有先抛出的线程才会结束。 所有其他人似乎都在std::call_once
语句之前等待。 因此我的问题是:等待第一个线程的线程通知是否有保证?
是否等待第一个线程完成保证的线程通知?
没有涉及通知,但如果我将您的问题解释为:
t4.join()
保证返回吗?
是的。
[thread.once.callonce]
template<class Callable, class... Args> void call_once(once_flag& flag, Callable&& func, Args&&... args);
效果 :不调用其func的
call_once
的执行是被动执行。
调用其func的call_once
的执行是一个活动执行。 活动执行应调用INVOKE(std::forward<Callable>(func), std::forward<Args>(args)...)
。
如果对func的这种调用抛出异常,则执行异常,否则返回。
异常执行应将异常传播给call_once
的调用者。 在任何给定的once_flag
的call_once
所有执行中:最多一个应该是返回执行; 如果有返回执行,则应该是最后一次执行; 只有在返回执行时才会执行被动执行 。同步 :对于任何给定的once_flag: 所有活动执行都按总顺序发生 ; 活动执行的完成与此总订单中下一个的开始同步; 并且返回的执行与所有被动执行的返回同步。
一个call_once
只有 1人将不被执行call_once
返回(:没扔的意思)。 由于遵守了总订单,因此可以保证:
t1
是主动例外执行或被动执行; t2
是主动例外执行或被动执行; t3
是主动返回执行; t4
是主动例外执行或被动执行; 并且由于被动执行返回,因此保证t4
返回。
用户cpplearner报告, pthread_once
的错误使问题中的程序挂起( 演示 )。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.