Boost::thread庫的使用

閱讀對象ios

本文假設讀者有幾下Skills多線程

[1]在C++中至少使用過一種多線程開發庫,有Mutex和Lock的概念。函數

[2]熟悉C++開發,在開發工具中,可以編譯、設置boost::thread庫。工具

環境

[1]Visual Studio 2005/2008 with SP1oop

[2]boost1.39/1.40開發工具

 

概要

經過實例介紹boost thread的使用方式,本文主要由線程啓動、Interruption機制、線程同步、等待線程退出、Thread Group幾個部份組成。ui

正文

線程啓動

線程能夠從如下三種方式啓動:this

第一種用struct結構的operator成員函數啓動:編碼

struct callablespa

{

   void operator()() {  這裏略去若干行代碼   }

};

 

這裏略去若干行代碼

 

Callable x;

Boost::thread t(x);

 

第二種以非成員函數形式啓動線程

 void  func(int nP)

 {  這裏略去若干行代碼

}

這裏略去若干行代碼

Boost::thread  t(func,123);

第三種以成員函數形式啓動線程

#include <boost/bind.hpp>

 

這裏略去若干行代碼

 

class testBind{

public:

  void testFunc(int i)

{

  cout<<」i=」<<i<<endl;

}

};

 

這裏略去若干行代碼

 

testBind tb;

boost::thread t(boost::bind(&testBind::testFunc,&tb,100));

Interruption機制

能夠經過thread對象的interrupt函數,通知線程,須要interrupt。線程運行到interruption point就能夠退出。

Interruption機制舉例:

#include "stdafx.h"

#include <iostream>

#include <boost/thread.hpp>

using namespace std;

 

void f()

{

     for(int i=1;i<0x0fffffff;i++)

     {

         if(i%0xffffff==0)

         {

              cout<<"i="<<((i&0x0f000000)>>24)<<endl;

             cout<<"boost::this_thread::interruption_requested()="<<boost::this_thread::interruption_requested()<<endl;

              if(((i&0x0f000000)>>24)==5)

              {

                   boost::this_thread::interruption_point();

              }

         }

     }

}

 

int _tmain(int argc, _TCHAR* argv[])

{

     boost::thread t(f);

     t.interrupt();

     t.join();  //等待線程結束

     return 0;

}

 

t.interrupt();告訴t線程,如今須要interrupt。 boost::this_thread::interruption_requested()能夠獲得當前線程是否有一個interrupt請求。如有 interrupt請求,線程在運行至interruption點時會結束。 boost::this_thread::interruption_point();就是一個interruption point。Interruption point有多種形式,較經常使用的有 boost::this_thread::sleep(boost::posix_time::seconds(5));當沒有interrupt請求 時,這條語句會讓當前線程sleep五秒,如有interrupt requirement線程結束。

如何使線程在運行到interruption point的時候,不會結束,能夠參考下面的例子:

#include "stdafx.h"

#include <iostream>

#include <boost/thread.hpp>

using namespace std;

 

void f()

{

     for(int i=1;i<0x0fffffff;i++)

     {

         if(i%0xffffff==0)

         {

              cout<<"i="<<((i&0x0f000000)>>24)<<endl;

 

             cout<<"boost::this_thread::interruption_requested()"<<boost::this_thread::interruption_requested()<<endl;

 

              if(((i&0x0f000000)>>24)==5)

              {

                   boost::this_thread::disable_interruption di;

                   {

                       boost::this_thread::interruption_point();

                   }

              }

         }

     }

}

 

int _tmain(int argc, _TCHAR* argv[])

{

     boost::thread t(f);

     t.interrupt();

     t.join();  //等待線程結束

 

     return 0;

}

 

 

注意boost::this_thread::disable_interruption這條語句的使用,它可使大括號內的interruption point不會中斷當前線程。

線程同步

Boost提供了多種lock致使上手須要較長時間,仍是看下面線程同步的例子比較簡單,相信在多數應用中足夠:

 

直接使用boost::mutex的例子

static boost::mutex g_m;

這裏略去若干行代碼

g_m.lock();

須要鎖定的代碼

g_m.unlock();

這裏略去若干行代碼

if(g_m.try_lock())

{

須要鎖定的代碼

}

這裏略去若干行代碼

 

 

使用lock guard的例子

#include <iostream>

#include <string>

#include <boost/thread.hpp>

#include <boost/thread/mutex.hpp>

#include <boost/thread/locks.hpp>

 

using namespace std;

 

static boost::mutex g_m;

 

void f(string strName)

{

     for(int i=1;i<0x0fffffff;i++)

     {

         if(i%0xffffff==0)

         {

              boost::lock_guard<boost::mutex> lock(g_m);

              cout<<"Name="<<strName<<" i="<<((i&0x0f000000)>>24)<<endl;

         }

     }

}

 

int _tmain(int argc, _TCHAR* argv[])

{

     boost::thread t(f,string("inuyasha"));

     boost::thread t2(f,string("kagula"));

     boost::thread t3(f,string("kikyou"));

 

     {

         boost::lock_guard<boost::mutex> lock(g_m);

         cout<<"thread id="<<t.get_id()<<endl;

     }

 

     t.join();

     t2.join();

     t3.join();

 

     return 0;

}

 

 

使用unique lock的例子

#include <iostream>

#include <string>

#include <boost/thread.hpp>

#include <boost/thread/mutex.hpp>

#include <boost/thread/locks.hpp>

 

using namespace std;

 

static boost::mutex g_m;

 

void f(string strName)

{

     cout<<"Thread name is "<<strName<<"-----------------begin"<<endl;

     for(int i=1;i<0x0fffffff;i++)

     {

         if(i%0xffffff==0)

         {

              boost::unique_lock<boost::mutex> lock(g_m);

 

              cout<<"Name="<<strName<<" i="<<((i&0x0f000000)>>24)<<endl;

             

              lock.unlock();

         }

     }

     cout<<"Thread name is "<<strName<<"-----------------end"<<endl;

}

 

int _tmain(int argc, _TCHAR* argv[])

{

     boost::thread t(f,string("inuyasha"));

     boost::thread t2(f,string("kagula"));

     boost::thread t3(f,string("kikyou"));

 

     t.join();

     t2.join();

     t3.join();

 

     return 0;

}

同Lock_guard相比

[1]Unique lock中有owns lock成員函數,可判斷,當前有沒有被lock。

[2]在構造Unique Lock時能夠指定boost::defer_lock_t參數推遲鎖定,直到Unique Lock實例調用Lock。或採用下面的編碼方式使用:

     boost::unique_lock<boost::mutex> lock(mut,boost::defer_lock);

     boost::unique_lock<boost::mutex> lock2(mut2,boost::defer_lock);

     boost::lock(lock,lock2);

[3]它能夠和Conditoin_variable配合使用。

[4]提供了try lock功能。

 

 

若是線程之間執行順序上有依賴關係,直接到boost官網中參考條件變量(Condition variables)的使用。官網關於Conditon Variables的說明仍是容易看懂的。

注意,使用一個不恰當的同步可能消耗掉1/2以上的cpu運算能力。

Thread Group

線程組使用示例,其中f函數在上面的例子已經定義

int _tmain(int argc, _TCHAR* argv[])

{

     boost::thread_group tg;

     tg.add_thread(new boost::thread(f,string("inuyasha")));

     tg.add_thread(new boost::thread(f,string("kagula")));

     tg.add_thread(new boost::thread(f,string("kikyou")));

     tg.join_all();

     return 0;

}

參考來源

http://blog.csdn.net/cedricporter/article/details/6909108

[1]www.boost.org

 

 

 

 

Boost.Thread可使用多線程執行可移植C++代碼中的共享數據。它提供了一些類和函數來管理線程自己,還有其它一些爲了實如今線程之間同步數據或者提供針對特定單個線程的數據拷貝。
頭文件:
#include <boost/thread.hpp>

線程定義
boost::thread 類是負責啓動和管理線程。每一個boost::thread對象表明一個單獨的執行線程,是不可拷貝的。因爲它是能夠被移動到,因此它們能夠被保存到會改變大小的容器中,而且從函數返回。這使得線程建立的詳細信息能夠被封裝到一個函數中。
boost::thread make_thread();

void f()
{
 boost::thread some_thread = make_thread();
 some_thread.join();
}


啓動線程
一個新的線程能夠經過傳遞一個可被調用的類型對象來啓動,這個對象能夠不須要給構造器參數就被喚醒。對象被拷貝到內存,並 且在最新建立的線程上喚醒。若是對象不能被拷貝,boost::ref能夠以引用的方式來傳遞給函數對象。在這種狀況下,用戶的boost.thread 必須確保對象的引用的生命期必須比最新建立的執行線程要長。

struct callable
{
    void operator()();
};

boost::thread copies_are_safe()
{
    callable x;
    return boost::thread(x);
} // x is destroyed, but the newly-created thread has a copy, so this is OK

boost::thread oops()
{
    callable x;
    return boost::thread(boost::ref(x));
} // x is destroyed, but the newly-created thread still has a reference
  // this leads to undefined behaviour


若是你用一個函數或者可調用的對象但願建立一個boost::thread 的實例須要提供一些參數,這些能夠經過給它的構造體傳遞另外的參數來辦到。

void find_the_question(int the_answer);

boost::thread deep_thought_2(find_the_question,42);
參數被拷貝到內部線程結構裏:若是須要傳遞一個引用,可使用boost::Ref,只是對可調用對象的引用。
沒有指定限制傳遞的額外參數的數量。

線程中的異常
若是傳入到boost::thread構造體的函數或者可調用的對象拋出了一個異常並且喚醒它的不是boosst::thread_interrupted類型,std::terminate()會被調用來結束這個線程。

等待
當表明一個執行線程的線程對象被破壞時,這個線程變成分離的,一旦它被分離,將會繼續執行知道喚醒由構造體提供的函數或者可調用對象執 行結束,或者程序已經結束。線程也能夠經過調用detach()成員函數來顯示的分離。在這種情形下,線程對象將不在表示一個當前分離的線程,而是一個非 線程體。
爲了等待一個線程執行完畢,必須使用join()和timed_join()成員函數。join()會阻塞調用的線程直到線程結束。若是 線程剛剛執行結束,或者它已經不表明一個線程,join()會當即返回。timed_join()也是相似的,可是調用它若是在指定的時間流逝後線程仍然 沒有結束它也會返回。

中斷
一個正在運行的線程能夠經過調用相應的boost::thread對象的interrupt()成員函數來中斷。當被中斷的線程在下次 執行一個指定的中斷點(或者若是它在同時執行一個的時候被鎖)並開啓中斷時,在被中斷的線程中就會拋出一個 boost::thread_interrupted異常。若是沒有被捕獲,這會致使結束被中斷線程的執行。與其餘異常同樣,棧就會被釋放,自動存儲期對 象的析構體將會被執行。
若是一個線程須要避免被中斷,能夠建立一個boost::this_thread::disable_interruption實例。這個類的對象在構造體建立線程的時候禁止了中斷,能夠在析構體調用以前的任意地方恢復容許中斷。
void f()
{
    // interruption enabled here
    {
        boost::this_thread::disable_interruption di;
        // interruption disabled
        {
            boost::this_thread::disable_interruption di2;
            // interruption still disabled
        } // di2 destroyed, interruption state restored
        // interruption still disabled
    } // di destroyed, interruption state restored
    // interruption now enabled
}

經過構造一個boost::this_thread::restore_interruption實例能夠臨時轉換一個 boost::this_thread::disable_interruption實例形成的影響,只要在有問題的地方傳遞一個 boost::this_thread::disable_interruption對象。這會從新恢復中斷狀態到當 boost::this_thread_diable_interruption對象被構造時,而且在次禁止中斷當 boost::this_thread::restore_interruption對象被破壞時。
void g()
{
    // interruption enabled here
    {
        boost::this_thread::disable_interruption di;
        // interruption disabled
        {
            boost::this_thread::restore_interruption ri(di);
            // interruption now enabled
        } // ri destroyed, interruption disable again
    } // di destroyed, interruption state restored
    // interruption now enabled
}
咱們能夠經過調用boost::this_thread::interruption_enabled()來查詢中斷的狀態。


預約義的中斷點
如下函數當容許中斷時可能會拋出boost::thread_interrupted異常。
boost::thread::join()
boost::thread::timed_join()
boost::condition_variable::wait()
boost::condition_variable::timed_wait()
boost::condition_variable_any::wait()
boost::condition_variable_any::timed_wait()
boost::thread::sleep()
boost::this_thread::sleep()
boost::this_thread::interruption_point()

線程IDboost::thread::id類能夠用來標識一個線程。每一個運行的執行線程都有一個特有的ID,能夠經過對應的boost::thread的get_id()成員函數來得到ID。

相關文章
相關標籤/搜索