1. 程式人生 > >boost::thread簡要分析(1):thread

boost::thread簡要分析(1):thread

昨天在寫作“大衛的Design Patterns學習筆記”過程中,編寫了一個多執行緒Producer-Consumer的示例,其中用到了boost::thread,但線上程同步的問題上遇到了些問題,到csdn和vckbase上發帖子問了一下,也沒人回答,沒有辦法,只好晚上回家搬出原始碼研究了一下,總算解決了問題,下面將自己的理解寫下來,與大家分享、討論。
注:以下討論基於boost1.32.0

boost::thread庫跟boost::function等很多其它boost組成庫不同,它只是一個跨平臺封裝庫(簡單的說,就是根據不同的巨集呼叫不同的API),裡面沒有太多的GP程式設計技巧,因此,研究起來比較簡單。

boost::thread庫主要由以下部分組成:
thread
mutex
scoped_lock
condition
xtime
barrier
下面依次解析如下:

thread
thread自然是boost::
thread庫的主角,但thread類的實現總體上是比較簡單的,前面已經說過,thread只是一個跨平臺的執行緒封裝庫,其中按照所使用的編譯選項的不同,分別決定使用Windows執行緒API還是pthread,或者Macintosh Carbon平臺的thread實現。以下只討論Windows,即使用BOOST_HAS_WINTHREADS的情況。
thread類提供了兩種建構函式:
thread::thread()
thread::thread(const function0<void>& threadfunc)
第一種建構函式用於呼叫GetCurrentThread構造一個當前執行緒的thread物件,第二種則通過傳入一個函式或者一個functor來建立一個新的執行緒。第二種情況下,thread類在其建構函式中間接呼叫CreateThread來建立執行緒,並將執行緒控制代碼儲存到成員變數m_thread中,並執行傳入的函式,或執行functor的operator
 ()方法來啟動工作執行緒。
此外,thread類有一個Windows下的程式設計師可能不大熟悉的成員函式join,執行緒(通常是主執行緒)可以通過呼叫join函式來等待另一執行緒(通常是工作執行緒)退出,join的實現也十分簡單,是呼叫WaitForSingleObject來實現的:
WaitForSingleObject(reinterpret_cast<HANDLE>(m_thread), INFINITE);
我們可以用以下三種方式啟動一個新執行緒:
1
、傳遞一個工作函式來構造一個工作執行緒
#include <boost/thread/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <iostream>

boost::mutex io_mutex;

void
 count()    // worker function
{
    for
 (int i = 0; i < 10; ++i)
    {

        boost::mutex::scoped_lock lock(io_mutex);
        std::cout << i << std::endl;
    }
}


int
 main(int argc, char* argv[])
{

    boost::thread thrd1(&count);
    boost::thread thrd2(&count);
    thrd1.join();
    thrd2.join();

    return
 0;
}

2
、傳遞一個functor物件來構造一個工作執行緒
#include <boost/thread/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <iostream>

boost::mutex io_mutex;

struct
 count
{

    count(int id) : id(id) { }

    void
 operator()()
    {

        for
 (int i = 0; i < 10; ++i)
        {

            boost::mutex::scoped_lock lock(io_mutex);        // lock io, will be explained soon.
            std::cout << id << ": " << i << std::endl;
        }
    }


    int
 id;
};


int
 main(int argc, char* argv[])
{

    boost::thread thrd1(count(1));
    boost::thread thrd2(count(2));
    thrd1.join();
    thrd2.join();
    return
 0;
}

3
、無需將類設計成一個functor,藉助bind來構造functor物件以建立工作執行緒
#include <boost/thread/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/bind.hpp>
#include <iostream>

boost::mutex io_mutex;

struct
 count
{

    static
 int num;
    int
 id;

    count() : id(num++) {}

    int
 do_count(int n)
    {

        for
 (int i = 0; i < n; ++i)
        {

            boost::mutex::scoped_lock lock(io_mutex);
            std::cout << id << ": " << i << std::endl;
        }

        return
 id;
    }
};


int
 count::num = 1;

int
 main(int argc, char* argv[])
{

    count c1;
    boost::thread thrd1(boost::bind(&count::do_count, &c1, 10));
    thrd1.join();
    return
 0;
}

其中bind是一個函式模板,它可以根據後面的例項化引數構造出一個functor來,上面的boost::bind(&count::do_count, &c1, 10)其實等價於返回了一個functor:
struct
 countFunctor
{

    int
 operator() ()
    {
        (&
c1)->do_count(10);    // just a hint, not actual code
    }
};

因此,以後就跟2中是一樣的了。