簡體   English   中英

用c ++ 11等價替換boost :: thread和boost :: mutex是否明智?

[英]Is it smart to replace boost::thread and boost::mutex with c++11 equivalents?

動機:我之所以考慮是因為我的天才項目經理認為提升是另一種依賴,而且它很可怕,因為“你依賴它”(我試着解釋提升的質量,然后放棄一段時間后:(我想做的更小的原因是我想學習c ++ 11的功能,因為人們會開始在其中編寫代碼。所以:

  1. #include<thread> #include<mutex>和boost等價物之間是否存在1:1映射?
  2. 你會考慮用c ++ 11替換boost東西嗎?
    東西。 我的用法是原始的,但有什么例子,當std沒有提供什么提升? 或者(褻瀆)反之亦然?

PS我使用GCC所以標題就在那里。

Boost.Thread和C ++ 11標准線程庫之間有幾點不同:

  • Boost支持線程取消,C ++ 11線程不支持
  • C ++ 11支持std::async ,但Boost不支持
  • Boost有一個boost::shared_mutex用於多讀者/單作者鎖定。 類似的std::shared_timed_mutex僅在C ++ 14( N3891 )之后可用,而std::shared_mutex僅在C ++ 17( N4508 )之后可用。
  • C ++ 11超時與Boost超時不同(盡管現在很快就會改變Boost.Chrono)。
  • 一些名稱是不同的(例如boost::unique_future vs std::future
  • std::thread的參數傳遞語義與boost::thread不同--- Boost使用boost::bind ,這需要可復制的參數。 std::thread允許僅移動類型(如std::unique_ptr作為參數傳遞。 由於使用了boost::bind ,嵌套綁定表達式中占位符(如_1的語義也可能不同。
  • 如果沒有顯式調用join()detach()那么boost::thread析構函數和賦值運算符將在被銷毀/賦值的線程對象上調用detach() 使用C ++ 11 std::thread對象,這將導致對std::terminate()的調用並中止應用程序。

為了澄清關於僅移動參數的觀點,以下是有效的C ++ 11,並且在新線程啟動時將int的所有權從臨時std::unique_ptr傳遞給f1的參數。 但是,如果你使用boost::thread那么它將無法工作,因為它在內部使用boost::bind ,並且無法復制std::unique_ptr GCC提供的C ++ 11線程庫中也存在一個錯誤,它阻止了這個工作,因為它在實現中也使用了std::bind

void f1(std::unique_ptr<int>);
std::thread t1(f1,std::unique_ptr<int>(new int(42)));

如果您正在使用Boost,那么如果您的編譯器支持它,您可以相對輕松地切換到C ++ 11線程(例如,Linux上的最新版本的GCC具有-std=c++0x可用的C ++ 11線程庫的大部分完整實現-std=c++0x模式)。

如果您的編譯器不支持C ++ 11線程,那么您可能能夠獲得第三方實現,例如Just :: Thread ,但這仍然是一個依賴項。

std::thread主要在boost::thread之后建模,但有一些區別

  • boost的不可復制,單句柄映射到一個os線程,語義被保留。 但是這個線程是可移動的,允許從工廠函數返回線程並放入容器中。
  • 這個提議增加了對boost::thread取消,這是一個重要的復雜問題。 此更改不僅對線程有影響,而且對C ++線程庫的其余部分也有很大影響。 人們相信,這種巨大的變化是有道理的,因為它的好處。
    • 線程析構函數現在必須在分離之前調用cancel,以避免在取消父線程時意外泄漏子線程。
    • 現在需要顯式分離成員啟用分離而不取消。
  • 線程句柄和線程標識的概念已分為兩類(它們在boost::thread中是相同的類)。 這是為了支持更容易操作和存儲線程標識。
  • 能夠創建一個保證比較等於沒有其他可連接線程的線程id( boost::thread沒有這個)。 這對於想要知道它是否由與前一個調用相同的線程執行的代碼來說很方便(遞歸互斥體是一個具體的例子)。
  • 存在一個“后門”來獲取本機線程句柄,以便客戶端可以根據需要使用底層操作系統來操作線程。

這是從2007年開始,所以有些點不再有效: boost::thread現在有一個native_handle函數,並且,正如評論者指出的那樣, std::thread不再有取消。

我在boost::mutexstd::mutex之間找不到任何顯着差異。

有一個原因是不遷移到std::thread

如果您使用靜態鏈接,由於這些gcc錯誤/功能, std::thread變得無法使用:

也就是說,如果你調用std::thread::detachstd::thread::join ,它將導致異常或崩潰,而boost::thread在這些情況下工作正常。

企業案例

如果您正在為需要在中等到大量操作系統上運行的企業編寫軟件,並因此在這些操作系統上使用各種編譯器和編譯器版本(尤其是相對較舊的版本)進行構建,我的建議是遠離C ++ 11現在一共。 這意味着你不能使用std::thread ,我建議使用boost::thread

基礎/技術創業案例

如果你正在編寫一個或兩個操作系統,你肯定知道你只需要構建一個主要支持C ++ 11的現代編譯器(例如VS2015,GCC 5.3,Xcode 7),而你還沒有依賴於boost庫,那么std::thread可能是個不錯的選擇。

我的經驗

我個人偏愛硬化,使用頻繁,高度兼容,高度一致的庫,例如boost與非常現代的替代品。 對於諸如線程之類的復雜編程主題尤其如此。 另外,我在很多環境,編譯器,線程模型等中使用boost::thread (以及一般的boost)取得了巨大的成功。當我選擇它時,我選擇了boost。

使用Visual Studio 2013時, std::mutex行為似乎與boost::mutex不同,這導致了一些問題(請參閱此問題 )。

關於在C ++ 17中添加的std :: shared_mutex

這里的其他答案提供了一般的差異的非常好的概述。 但是, std::shared_mutex有幾個問題可以提升解決方案。

  1. 可升級的突變。 這些在std::thread中不存在。 它們允許讀者升級為作家, 而不允許任何其他作者進入你之前 這些允許您在讀取模式下執行諸如預處理大型計算(例如,重新索引數據結構)之類的操作,然后升級到寫入以應用重新索引,同時僅在短時間內保持寫入鎖定。

  2. 公平。 如果您使用std::shared_mutex進行持續讀取活動,則您的編寫器將無限期地進行軟鎖定。 這是因為如果另一位讀者出現,他們將始終優先考慮。 使用boost:shared_mutex ,所有線程最終都將獲得優先權。 (1)讀者和作家都不會被餓死。

tl; dr是如果你有一個非常高吞吐量的系統,沒有停機時間和非常高的爭用, std::shared_mutex將永遠不會為你工作,如果沒有手動建立一個優先系統。 boost::shared_mutex可以開箱即用,但在某些情況下你可能需要修改它。 我認為std::shared_mutex的行為是在大多數使用它的代碼中等待發生的潛在錯誤。

(1) 它使用實際算法基於OS線程調度程序。 根據我的經驗,當讀取飽和時,Windows上的暫停(獲取寫鎖定時)比OSX / Linux上的暫停時間長。

我嘗試使用std中的shared_ptr而不是boost,我實際上在這個類的gcc實現中發現了一個bug。 我的應用程序崩潰是因為析構函數被調用了兩次(這個類應該是線程安全的,不應該生成這樣的問題)。 移動到boost :: shared_ptr后,所有問題都消失了。 目前C ++ 11的實現仍然不成熟。

Boost還有更多功能。 例如,std版本中的頭文件不向流提供序列化程序(即cout << duration)。 Boost有許多庫使用自己的等價物,但不與std版本合作。

總結一下 - 如果你已經有一個使用boost編寫的應用程序,那么保持你的代碼是更安全的,而不是花些錢去轉向C ++ 11標准。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM