C++ Boost Lockfree超詳細(xì)講解使用方法
一、說(shuō)明
Boost.Lockfree 提供線程安全和無(wú)鎖容器。可以從多個(gè)線程訪問(wèn)此庫(kù)中的容器,而無(wú)需同步訪問(wèn)。
在 1.56.0 版本中,Boost.Lockfree 只提供了兩個(gè)容器:boost::lockfree::queue 類型的隊(duì)列和 boost::lockfree::stack 類型的棧。對(duì)于隊(duì)列,可以使用第二個(gè)實(shí)現(xiàn):boost::lockfree::spsc_queue。此類針對(duì)只有一個(gè)線程寫入隊(duì)列和只有一個(gè)線程從隊(duì)列讀取的用例進(jìn)行了優(yōu)化。類名中的縮寫 spsc 代表單一生產(chǎn)者/單一消費(fèi)者。
二、示例和代碼
示例 46.1。使用 boost::lockfree::spsc_queue
#include <boost/lockfree/spsc_queue.hpp> #include <thread> #include <iostream> boost::lockfree::spsc_queue<int> q{100}; int sum = 0; void produce() { for (int i = 1; i <= 100; ++i) q.push(i); } void consume() { int i; while (q.pop(i)) sum += i; } int main() { std::thread t1{produce}; std::thread t2{consume}; t1.join(); t2.join(); consume(); std::cout << sum << '\n'; }
示例 46.1 使用容器 boost::lockfree::spsc_queue。第一個(gè)執(zhí)行函數(shù) produce() 的線程將數(shù)字 1 到 100 添加到容器中。第二個(gè)線程執(zhí)行 consume(),從容器中讀取數(shù)字并將它們相加。因?yàn)槿萜?boost::lockfree::spsc_queue 明確支持來(lái)自兩個(gè)線程的并發(fā)訪問(wèn),所以不需要同步線程。
請(qǐng)注意,函數(shù) consume() 會(huì)在線程終止后被第二次調(diào)用。這需要計(jì)算所有 100 個(gè)數(shù)字的總數(shù),即 5050。因?yàn)?consume() 在循環(huán)中訪問(wèn)隊(duì)列,它讀取數(shù)字的速度可能比 produce() 插入數(shù)字的速度快。如果隊(duì)列為空,pop() 返回 false。因此,執(zhí)行 consume() 的線程可能會(huì)終止,因?yàn)榱硪粋€(gè)線程中的 produce() 無(wú)法足夠快地填充隊(duì)列。如果執(zhí)行 produce() 的線程終止,那么很明顯所有數(shù)字都已添加到隊(duì)列中。第二次調(diào)用 consume() 確保將可能尚未讀取的數(shù)字添加到 sum 中。
隊(duì)列的大小被傳遞給構(gòu)造函數(shù)。因?yàn)?boost::lockfree::spsc_queue 是用循環(huán)緩沖區(qū)實(shí)現(xiàn)的,所以示例 46.1 中的隊(duì)列容量為 100 個(gè)元素。如果由于隊(duì)列已滿而無(wú)法添加值,則 push() 返回 false。該示例不檢查 push() 的返回值,因?yàn)榍『糜?100 個(gè)數(shù)字被添加到隊(duì)列中。因此,100 個(gè)元素就足夠了。
示例 46.2。 boost::lockfree::spsc_queue 和 boost::lockfree::capacity
#include <boost/lockfree/spsc_queue.hpp> #include <boost/lockfree/policies.hpp> #include <thread> #include <iostream> using namespace boost::lockfree; spsc_queue<int, capacity<100>> q; int sum = 0; void produce() { for (int i = 1; i <= 100; ++i) q.push(i); } void consume() { while (q.consume_one([](int i){ sum += i; })) ; } int main() { std::thread t1{produce}; std::thread t2{consume}; t1.join(); t2.join(); q.consume_all([](int i){ sum += i; }); std::cout << sum << '\n'; }
示例 46.2 與前面的示例類似,但這次循環(huán)緩沖區(qū)的大小是在編譯時(shí)設(shè)置的。這是通過(guò)模板 boost::lockfree::capacity 完成的,它需要容量作為模板參數(shù)。 q 是用默認(rèn)構(gòu)造函數(shù)實(shí)例化的——容量不能在運(yùn)行時(shí)設(shè)置。
函數(shù) consume() 已更改為使用 consume_one() 而不是 pop() 來(lái)讀取數(shù)字。 lambda 函數(shù)作為參數(shù)傳遞給 consume_one()。 consume_one() 就像 pop() 一樣讀取一個(gè)數(shù)字,但該數(shù)字不是通過(guò)對(duì)調(diào)用者的引用返回的。它作為唯一參數(shù)傳遞給 lambda 函數(shù)。
當(dāng)線程終止時(shí),main() 調(diào)用成員函數(shù) consume_all(),而不是 consume()。 consume_all() 的工作方式與 consume_one() 類似,但要確保隊(duì)列在調(diào)用后為空。只要隊(duì)列中有元素,consume_all() 就會(huì)調(diào)用 lambda 函數(shù)。
示例 46.2 再次將 5050 寫入標(biāo)準(zhǔn)輸出。
示例 46.3。具有可變?nèi)萜鞔笮〉?boost::lockfree::queue
#include <boost/lockfree/queue.hpp> #include <thread> #include <atomic> #include <iostream> boost::lockfree::queue<int> q{100}; std::atomic<int> sum{0}; void produce() { for (int i = 1; i <= 10000; ++i) q.push(i); } void consume() { int i; while (q.pop(i)) sum += i; } int main() { std::thread t1{produce}; std::thread t2{consume}; std::thread t3{consume}; t1.join(); t2.join(); t3.join(); consume(); std::cout << sum << '\n'; }
示例 46.3 在兩個(gè)線程中執(zhí)行 consume()。因?yàn)橛卸鄠€(gè)線程從隊(duì)列中讀取,所以不得使用類 boost::lockfree::spsc_queue。此示例改為使用 boost::lockfree::queue。
多虧了 std::atomic,對(duì)變量 sum 的訪問(wèn)現(xiàn)在也是線程安全的。
隊(duì)列的大小設(shè)置為 100——這是傳遞給構(gòu)造函數(shù)的參數(shù)。但是,這只是初始大小。默認(rèn)情況下,boost::lockfree::queue 不使用循環(huán)緩沖區(qū)實(shí)現(xiàn)。如果添加到隊(duì)列中的項(xiàng)目多于設(shè)置的容量,則會(huì)自動(dòng)增加。如果初始大小不夠,boost::lockfree::queue 會(huì)動(dòng)態(tài)分配額外的內(nèi)存。
這意味著 boost::lockfree::queue 不一定是無(wú)鎖的。 boost::lockfree::queue 默認(rèn)使用的分配器是 boost::lockfree::allocator,它基于 std::allocator。因此,此分配器確定 boost::lockfree::queue 是否是無(wú)約束的無(wú)鎖。
#include <boost/lockfree/queue.hpp> #include <thread> #include <atomic> #include <iostream> using namespace boost::lockfree; queue<int, fixed_sized<true>> q{10000}; std::atomic<int> sum{0}; void produce() { for (int i = 1; i <= 10000; ++i) q.push(i); } void consume() { int i; while (q.pop(i)) sum += i; } int main() { std::thread t1{produce}; std::thread t2{consume}; std::thread t3{consume}; t1.join(); t2.join(); t3.join(); consume(); std::cout << sum << '\n'; }
示例 46.3 在兩個(gè)線程中執(zhí)行 consume()。因?yàn)橛卸鄠€(gè)線程從隊(duì)列中讀取,所以不得使用類 boost::lockfree::spsc_queue。此示例改為使用 boost::lockfree::queue。
多虧了 std::atomic,對(duì)變量 sum 的訪問(wèn)現(xiàn)在也是線程安全的。
隊(duì)列的大小設(shè)置為 100——這是傳遞給構(gòu)造函數(shù)的參數(shù)。但是,這只是初始大小。默認(rèn)情況下,boost::lockfree::queue 不使用循環(huán)緩沖區(qū)實(shí)現(xiàn)。如果添加到隊(duì)列中的項(xiàng)目多于設(shè)置的容量,則會(huì)自動(dòng)增加。如果初始大小不夠,boost::lockfree::queue 會(huì)動(dòng)態(tài)分配額外的內(nèi)存。
這意味著 boost::lockfree::queue 不一定是無(wú)鎖的。 boost::lockfree::queue 默認(rèn)使用的分配器是 boost::lockfree::allocator,它基于 std::allocator。因此,此分配器確定 boost::lockfree::queue 是否是無(wú)約束的無(wú)鎖。
示例 46.4。具有恒定容器大小的 boost::lockfree::queue
到此這篇關(guān)于C++ Boost Lockfree超詳細(xì)講解使用方法的文章就介紹到這了,更多相關(guān)C++ Boost Lockfree內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C語(yǔ)言開(kāi)發(fā)實(shí)現(xiàn)貪吃蛇小游戲
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言開(kāi)發(fā)實(shí)現(xiàn)貪吃蛇小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-10-10C++11中std::function與std::bind的用法實(shí)例
大家都知道C++11中增加了許多的新特性,下面這篇文章主要給大家介紹了關(guān)于C++11中std::function與std::bind的用法,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-05-05c++實(shí)現(xiàn)簡(jiǎn)單隨機(jī)數(shù)的代碼
在本篇文章里小編給大家整理的是一篇關(guān)于c++實(shí)現(xiàn)簡(jiǎn)單隨機(jī)數(shù)的代碼內(nèi)容,有需要的朋友們可以跟著學(xué)習(xí)下。2021-05-05C++?指針和對(duì)象成員訪問(wèn)的區(qū)別:`.`?與?`->`?的使用小結(jié)
在學(xué)習(xí)?C++?時(shí),常常會(huì)遇到訪問(wèn)對(duì)象成員的兩種符號(hào):.?和?->,這兩個(gè)符號(hào)看似簡(jiǎn)單,但它們的正確使用卻需要理解指針和對(duì)象的本質(zhì)差異,本文介紹C++?指針和對(duì)象成員訪問(wèn)的區(qū)別:`.`?與?`->`?的使用指南,感興趣的朋友一起看看吧2024-12-12C語(yǔ)言對(duì)磁盤文件進(jìn)行快速排序簡(jiǎn)單實(shí)例
這篇文章主要介紹了C語(yǔ)言對(duì)磁盤文件進(jìn)行快速排序簡(jiǎn)單實(shí)例的相關(guān)資料,需要的朋友可以參考下2017-06-06詳解圖的應(yīng)用(最小生成樹、拓?fù)渑判?、關(guān)鍵路徑、最短路徑)
這篇文章主要介紹了圖的應(yīng)用(最小生成樹、拓?fù)渑判?、關(guān)鍵路徑、最短路徑),需要的朋友可以參考下2015-08-08C++11新特性中auto 和 decltype 區(qū)別和聯(lián)系
這篇文章主要介紹了C++11新特性中auto 和 decltype 區(qū)別和聯(lián)系的相關(guān)資料,需要的朋友可以參考下2017-01-01