<menu id="w8yyk"><menu id="w8yyk"></menu></menu>
  • <dd id="w8yyk"><nav id="w8yyk"></nav></dd>
    <menu id="w8yyk"></menu>
    <menu id="w8yyk"><code id="w8yyk"></code></menu>
    <menu id="w8yyk"></menu>
    <xmp id="w8yyk">
    <xmp id="w8yyk"><nav id="w8yyk"></nav>
  • 網站首頁 > 物聯資訊 > 技術分享

    Boost::thread庫的使用

    2016-09-28 00:00:00 廣州睿豐德信息科技有限公司 閱讀
    睿豐德科技 專注RFID識別技術和條碼識別技術與管理軟件的集成項目。質量追溯系統、MES系統、金蝶與條碼系統對接、用友與條碼系統對接

    閱讀對象

    本文假設讀者有幾下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));

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

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

    RFID管理系統集成商 RFID中間件 條碼系統中間層 物聯網軟件集成
    最近免费观看高清韩国日本大全