2013-07-09 44 views
4

CPPReference開始,並沒有明確說明如果鎖定不會導致死鎖,則鎖定函數std::mutex不會被拋出。如果一切看起來都很「好」,std :: mutex :: lock會引發事件嗎?

PThread's lock只有一個死鎖錯誤。我不知道窗口的線程實現。我也不知道他們是否使用其他線程作爲後端的std::thread/std::mutex

所以我的問題是「我應該寫我的代碼,如果沒有特殊原因,有時候,鎖可能會失敗?」。

我實際上需要鎖定一些noexcept方法中的互斥鎖,並且我想確保它們是noexcept。

+0

+1鎖定可能拋出真的不是一件好事恕我直言,當然我們需要在析構函數中調用它們,最後我寫了[自己的互斥類](http://stackoverflow.com/questions/16568990/locking-a-mutex-in- a-destructor-in-c11/16597680#16597680) – Arnaud

回答

7

std::mutex::lock()構件功能不被聲明爲noexcept和從部分30.4.1.2互斥類型C++ 11標準的(草案n3337),第6:

表達m.lock()應很好-formed並具有以下語義:

  • ...
  • 拋出:system_error當需要異常(30.2.2)。
  • 錯誤條件:
    • operation_not_permitted - 如果線程沒有權限執行操作。
    • resource_deadlock_would_occur - 如果實現檢測到會發生死鎖。
    • device_or_resource_busy - 如果互斥鎖已經被鎖定並且阻塞是不可能的。

這意味着使用任何mutex::lock()功能不能標記noexcept,除非該功能能夠處理該異常本身並防止其propogating給調用者。


我無法對這些錯誤情況發生的歷史的可能性發表評論,但相對於std::mutexresource_deadlock_would_occur(其中可能拋出)表示在代碼中的錯誤,而不是運行時出現故障因爲如果線程試圖鎖定它已經擁有的std::mutex,則可能會引發此錯誤。從部分30.4.1.2.1類互斥,第4條:

[注:如果擁有一個互斥對象的線程調用鎖()該對象上的程序可以死鎖。如果實現可以檢測到死鎖,則可能會觀察到resource_deadlock_would_occur錯誤情況。末端注]

通過選擇std::mutex爲鎖定類型的程序員,明確指出同一線程試圖鎖定mutex它已經被鎖定是不可能的。 它是一個線程執行的合法路徑重新鎖定mutex然後std:recursive_mutex是更合適的選擇(但更改爲recursive_lock並不意味着lock()函數是免費例外)。

+0

我知道resource_deadlock_would_occur可以拋出,但是我可以(應該)阻止這個發生,因爲正如你所說的那樣,它意味着一個bug。我不能爲另外兩個人做任何事情,因爲中止不是一種選擇,我必須處理它們:) –

1

假設互斥體不會拋出,如果可以的話保證沒有任何錯誤條件(如hmjd的答案中所述)存在。如何將該調用放入noexcept函數取決於您希望如何處理(非常不可能的)失敗。如果noexcept的缺省值(要調用std::terminate是可以接受的,則不需要執行任何操作。如果要記錄不可能的錯誤,請將函數包裝在try/catch子句中。

相關問題