C++ Boost Atomic詳細講解
一、說明
Boost.Atomic 提供類 boost::atomic,可用于創(chuàng)建原子變量。它們被稱為原子變量,因為所有訪問都是原子的。 Boost.Atomic 用于多線程程序,當(dāng)在一個線程中訪問變量不應(yīng)被訪問相同變量的另一個線程中斷時。如果沒有 boost::atomic,從多個線程訪問共享變量的嘗試將需要與鎖同步。
boost::atomic 取決于支持原子變量訪問的目標(biāo)平臺。否則,boost::atomic 使用鎖。該庫允許您檢測目標(biāo)平臺是否支持原子變量訪問。
如果您的開發(fā)環(huán)境支持 C++11,則不需要 Boost.Atomic。 C++11 標(biāo)準(zhǔn)庫提供了一個頭文件 atomic,它定義了與 Boost.Atomic 相同的功能。例如,您會發(fā)現(xiàn)一個名為 std::atomic 的類。
Boost.Atomic 支持與標(biāo)準(zhǔn)庫大致相同的功能。雖然一些函數(shù)在 Boost.Atomic 中被重載,但它們在標(biāo)準(zhǔn)庫中可能有不同的名稱。標(biāo)準(zhǔn)庫還提供了一些 Boost.Atomic 中缺少的函數(shù),例如 std::atomic_init() 和 std::kill_dependency()。
二、示例和代碼
示例 45.1。使用 boost::atomic
#include <boost/atomic.hpp> #include <thread> #include <iostream> boost::atomic<int> a{ 0 }; void thread() { ++a; } void thread_s() { std::cout << "Hello Thread" << a << '\n'; } int main() { std::thread t1{ thread }; std::thread t2{ thread }; std::thread t3{ thread_s }; std::thread t4{ thread_s }; t1.join(); t2.join(); t3.join(); t4.join(); std::cout << a << '\n'; }
示例 45.1 使用兩個線程來遞增 int 變量 a。該示例使用 boost::atomic 代替鎖來對 a 進行原子訪問。該示例將 2 寫入標(biāo)準(zhǔn)輸出。
boost::atomic 之所以有效,是因為一些處理器支持對變量的原子訪問。如果增加一個 int 變量是一個原子操作,則不需要鎖。如果此示例在無法將變量遞增為原子操作的平臺上運行,則 boost::atomic 使用鎖。
示例 45.2。 boost::atomic 帶鎖或不帶鎖
#include <boost/atomic.hpp> #include <iostream> int main() { std::cout.setf(std::ios::boolalpha); boost::atomic<short> s; std::cout << s.is_lock_free() << '\n'; boost::atomic<int> i; std::cout << i.is_lock_free() << '\n'; boost::atomic<long> l; std::cout << l.is_lock_free() << '\n'; }
您可以在原子變量上調(diào)用 is_lock_free() 來檢查是否在沒有鎖的情況下訪問該變量。如果您在 Intel x86 處理器上運行示例,它會顯示 true 三次。如果您在沒有對 short、int 和 long 變量進行無鎖訪問的處理器上運行它,則會顯示 false。
Boost.Atomic 提供了 BOOST_ATOMIC_INT_LOCK_FREE 和 BOOST_ATOMIC_LONG_LOCK_FREE 宏來在編譯時檢查哪些數(shù)據(jù)類型支持無鎖訪問。
示例 45.2 僅使用整型數(shù)據(jù)類型。您不應(yīng)將 boost::atomic 與 std::string 或 std::vector 等類一起使用。 Boost.Atomic 支持整數(shù)、指針、布爾值 (bool) 和普通類。整數(shù)類型的示例包括 short、int 和 long。普通類定義可以使用 std::memcpy() 復(fù)制的對象。
示例 45.3。 boost::atomic 和 boost::memory_order_seq_cst
#include <boost/atomic.hpp> #include <thread> #include <iostream> boost::atomic<int> a{0}; void thread() { a.fetch_add(1, boost::memory_order_seq_cst); } int main() { std::thread t1{thread}; std::thread t2{thread}; t1.join(); t2.join(); std::cout << a << '\n'; }
示例 45.3 增加了兩次——這次不是使用 operator++,而是調(diào)用 fetch_add()。成員函數(shù) fetch_add() 可以采用兩個參數(shù):a 應(yīng)該遞增的數(shù)字和內(nèi)存順序。
內(nèi)存順序指定內(nèi)存訪問操作必須發(fā)生的順序。默認情況下,這個順序是不確定的,不依賴于代碼行的順序。只要程序表現(xiàn)得好像內(nèi)存訪問操作是按源代碼順序執(zhí)行的,編譯器和處理器就可以更改順序。此規(guī)則僅適用于線程。如果使用多個線程,內(nèi)存訪問順序的變化會導(dǎo)致程序運行錯誤。 Boost.Atomic 支持在訪問變量時指定內(nèi)存順序,以確保內(nèi)存訪問在多線程程序中以所需的順序發(fā)生。
注意
指定內(nèi)存順序可優(yōu)化性能,但會增加復(fù)雜性并使編寫正確代碼變得更加困難。因此,在實踐中,您應(yīng)該有充分的理由使用內(nèi)存順序。
示例 45.3 使用內(nèi)存順序 boost::memory_order_seq_cst 將 a 遞增 1。內(nèi)存順序代表順序一致性。這是最嚴格的內(nèi)存順序。在 fetch_add() 調(diào)用之前出現(xiàn)的所有內(nèi)存訪問必須在執(zhí)行此成員函數(shù)之前發(fā)生。在 fetch_add() 調(diào)用之后出現(xiàn)的所有內(nèi)存訪問都必須在執(zhí)行此成員函數(shù)之后發(fā)生。編譯器和處理器可以在調(diào)用 fetch_add() 之前和之后重新排序內(nèi)存訪問,但它們不得將內(nèi)存訪問從調(diào)用 fetch_add() 之前移動到調(diào)用之后,反之亦然。 boost::memory_order_seq_cst 是雙向內(nèi)存訪問的嚴格邊界。
到此這篇關(guān)于C++ Boost Atomic詳細講解的文章就介紹到這了,更多相關(guān)C++ Boost Atomic內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C數(shù)據(jù)結(jié)構(gòu)中串簡單實例
這篇文章主要介紹了C數(shù)據(jù)結(jié)構(gòu)中串簡單實例的相關(guān)資料,需要的朋友可以參考下2017-06-06C++利用隨機策略實現(xiàn)優(yōu)化二叉樹操作效率
這篇文章中我們主要來詳細探討隨機化二叉搜索樹的基本思想、實現(xiàn)方法,以及如何在C++中應(yīng)用這些策略來優(yōu)化我們的數(shù)據(jù)結(jié)構(gòu),感興趣的可以了解下2024-02-02