天天看點

Boost::thread庫的使用

閱讀對象

本文假設讀者有幾下Skills

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

[2]熟悉C++開發,在開發工具中,能夠編譯、設定boost::thread庫。

[1]Visual Studio 2005/2008 with SP1

[2]boost1.39/1.40

通過執行個體介紹boost thread的使用方式,本文主要由線程啟動、Interruption機制、線程同步、等待線程退出、Thread Group幾個部份組成。

線程可以從以下三種方式啟動:

第一種用struct結構的operator成員函數啟動:

struct callable

{

   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));

可以通過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的時候,不會結束,可以參考下面的例子:

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

                   boost::this_thread::disable_interruption di;

                   {

                       boost::this_thread::interruption_point();

                   }

注意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 <string>

#include <boost/thread/mutex.hpp>

#include <boost/thread/locks.hpp>

void f(string strName)

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

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

     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();

使用unique lock的例子

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

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

              lock.unlock();

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

同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運算能力。

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

     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();

參考來源

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

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()

    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執行個體。這個類的對象在構造體建立線程的時候禁止了中斷,可以在析構體調用之前的任意地方恢複允許中斷。

    // 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()

            boost::this_thread::restore_interruption ri(di);

            // interruption now enabled

        } // ri destroyed, interruption disable again

我們可以通過調用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()

線程ID

boost::thread::id類可以用來辨別一個線程。每個運作的執行線程都有一個特有的ID,可以通過對應的boost::thread的get_id()成員函數來獲得ID。

c++

繼續閱讀