【Boost】boost库中thread多线程详解8——call_once仅运行一次
還有一個問題沒有解決:如何使得初始化工作(比如說構造函數)也是線程安全的。比方說,如果一個引用程序要產生唯一的全局的對象,由于實例化順序的問題,某個函數會被調用來返回一個靜態的對象,它必須保證第一次被調用時就產生這個靜態的對象。這里的問題就是如果多個線程同時調用了這個函數,那么這個靜態對象的構造函數就會被調用多次,這樣錯誤產生了。解決這個問題的方法就是所謂的“一次實現”(once routine)。“一次實現”在一個應用程序只能執行一次。如果多個線程想同時執行這個操作,那么真正執行的只有一個,而其他線程必須等這個操作結束。為了保證它只被執行一次,這個routine由另一個函數間接的調用,而這個函數傳給它一個指針以及一個標志著這個routine是否已經被調用的特殊標志。這個標志是以靜態的方式初始化的,這也就保證了它在編譯期間就被初始化而不是運行時。因此也就沒有多個線程同時將它初始化的問題了。Boost線程庫提供了boost::call_once來支持“一次實現”,并且定義了一個標志boost::once_flag及一個初始化這個標志的宏BOOST_ONCE_INIT。List6是一個使用了boost::call_once的例子。其中定義了一個靜態的全局整數,初始值為0;還有一個由BOOST_ONCE_INIT初始化的靜態boost::once_flag實例。main函數創建了兩個線程,它們都想通過傳入一個函數調用boost::call_once來初始化這個全局的整數,這個函數是將它加1。main函數等待著兩個線程結束,并將最后的結果輸出的到std::cout。由最后的結果可以看出這個操作確實只被執行了一次,因為它的值是1。
#include <boost/thread/thread.hpp> #include <boost/thread/once.hpp> #include <iostream>int i = 0; boost::once_flag flag = BOOST_ONCE_INIT;void init() {++i; }void thread() {boost::call_once(&init, flag); }int main(int argc, char* argv[]) {boost::thread thrd1(&thread);boost::thread thrd2(&thread);thrd1.join();thrd2.join();std::cout << i << std::endl;return 0; }#include <iostream> #include <boost/thread/thread.hpp> #include <boost/thread/once.hpp>// Some sort of connection class that should only be initialized once struct Conn {static void init( ) {++i_;}static boost::once_flag init_;static int i_;// ... };int Conn::i_ = 0; boost::once_flag Conn::init_ = BOOST_ONCE_INIT;void worker( ) {boost::call_once(Conn::init, Conn::init_);// Do the real work... }Conn c; // You probably don't want to use a global, so see the// next Recipeint main( ) {boost::thread_group grp;for (int i = 0; i < 100; ++i)grp.create_thread(worker);grp.join_all( );std::cout << c.i_ << '\n';// c.i_ = 1 }
一個共享資源不得不在某個地方被初始化,并且你希望第一次使用這個資源的線程來完成初始化工作。一個once_flag類型和call_once函數能夠保證多個線程不會重復的初始化同一個對象。首先,必須使用BOOST_ONCE_INIT宏來初始化這個once_flag對象。boost::once_flag Conn::init_ = BOOST_ONCE_INIT; 之后調用call_once函數,boost::call_once(Conn::init, Conn::init_); 第一個形參是希望被執行一次的初始化函數的地址。
總結
以上是生活随笔為你收集整理的【Boost】boost库中thread多线程详解8——call_once仅运行一次的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Boost】boost库中thread
- 下一篇: 【Boost】boost库中thread