![](/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.