2017-04-20 66 views
1

我跑進造成這種行爲的錯誤:通過的std :: call_once的調用的函數調用將掛起:: once_flag

#include <mutex> 

std::once_flag onceFlag; 

void get() { 
    std::call_once(onceFlag, [](){ get(); }); 
} 

int main(int argc, char* argv[]) { 
    get(); 
    return 0; 
} 

的另一種方式把它將會是:

#include <mutex> 

std::once_flag onceFlag; 

int main(int argc, char* argv[]) { 
    std::call_once(onceFlag, 
     [](){ 
      std::call_once(onceFlag, 
       [](){} 
      ); 
     } 
    ); 

    return 0; 
} 

據我在閱讀cppreference這裏(http://en.cppreference.com/w/cpp/thread/call_once),這是可以預料的,因爲在第一次調用到std :: call_once的尚未執行完畢:

在上述 執行所選功能成功完成之前,組中沒有調用返回,即 未通過異常退出。

爲什麼上述要求?在函數調用之前,不能設置once_flag,並且在拋出異常時重置?

+0

簡答:因爲委員會決定應該。 – Caleth

回答

2

爲什麼上述要求?在函數被調用之前,不能設置once_flag,並且在拋出異常時重置?

那麼沒有。在您的建議once_flag將被設置,然後在任何故障的情況下重新設置。這可能會造成競爭條件。考慮2線程的這種情況:th1和​​。兩個人都在做一些任務,只需要完成一次。線程依賴once_flag按照您的建議進行工作。 th1在守護着once_flag的功能。​​正在檢查once_flag條件並停止執行,因爲從它的pov任務完成。在th1任務執行期間拋出異常,從th1 pov就可以了,因爲其他一些worker會完成執行。任務從未完成,因爲th1失敗,並且once_flag未設置,但​​已完成,因爲once_flag已設置,並且它假定任務已完成。

根據目前的要求,這種不一致不會發生。