boost之併發編程

1.      Thread創建方法:(注意bind和thread以函數作爲參數時,如果函數是靜態成員函數或者普通函數,可以傳函數名func或函數名取地址&func,但是如果是非靜態成員函數,必須傳函數名取地址)

1)     利用普通函數創建線程,例如:boost::thread thrd(&func,2);或boost::threadthrd(func,2);

2)     利用靜態成員函數創建線程,例如:boost::threadthrd(&Base::static_func,2);或boost::thread thrd(Base:: static_func,2);

3)     利用非靜態成員函數創建線程,例如:boost::threadthrd(&Base::func, pointer,2);

4)     利用函數對象也可以創建線程

例如利用bind實現回調函數註冊:

class B{
public:
    void FuncB(int n){
        std::cout<<"Func B:"<<n<<std::endl;
    }
};
class A{
public:
    void start(){
        for(int i = 0; i < 1000; ++i){
            this_thread::sleep(boost::posix_time::milliseconds(1000));
            m_callHandler(i);
        }
    }
    template<class Callable, class A>
    void registerHandler(Callable call, A a){
        m_callHandler = boost::bind(call, a, _1);
    }
    template<class Callable>
    void registerHandler(Callable call){
        m_callHandler = boost::bind(call, _1);
    }
private:
    callFuncInt_t m_callHandler;
};

2.      Mutex的分類(一般結合lock模板使用):

1)     mutex, try_mutex爲獨佔型互斥量,後者和mutex爲同義詞,兼容以前版本 

2)     timed_mutex 爲定時獨佔型,增加了提供超時鎖定功能,比 mutex多了兩個成員函數:try_lock_for()和try_lock_until()

3)     recursive_mutex爲遞歸型互斥量,支持多次鎖定,並進行相應的多次解鎖,可以減少死鎖的概率。而mutex如果在一個線程中在執行中需要再次獲得鎖的情況,就會死鎖。recursive_try_mutex後者和mutex爲同義詞,兼容以前版本 

4)     recursive_timed_mutex爲定時遞歸型。其實就是timed_mutex和recursvie_mutex的組合版本

5)     shared_mutex爲共享型互斥量,shared_mutex除了提供lock和unlock方法外,還有shared_lock和shared_unlock方法,允許多個(讀者)線程同時加鎖、解鎖

6)     upgrade_mutex爲升級互斥量,可以在任何時候升級爲獨佔型互斥量,如果沒當時沒有現成擁有共享權限,即可立即獲得獨佔權限。以下是原文解釋:Thethread with upgradable ownership may at any time attempt to upgrade thatownership to exclusive ownership. If no other threads have shared ownership,the upgrade is completed immediately, and the thread now has exclusiveownership, which must be relinquished by a call to unlock()

3.      lock模版分類:

1)     lock_guard<T>:簡單的獨佔鎖,比boost::unique_lock更輕量級的lock,只有兩個public方法,即構造和析構函數,不提供提前unlock的功能。

2)     unique_lock<T>:獨佔鎖,unique_lock<T>對T沒有限制,如果T是shared_mutex,則在執行加鎖和解鎖時會調用shared_lock和shared_unlock方法,否則,則執行一般的lock和unlock方法

3)     shared_lock<T>:共享鎖,shared_lock<T>只允許T是shared_mutex

4)     scoped_lock:位於mutex::scoped_lock,其實就是typedefunique_lock<mutex> scoped_lock;

5)     upgrade_lock<T>:升級鎖,不常用,暫時沒有遇到使用場景

4.      條件變量:condition_variable_any 介紹與condition_variable類似,只不過condition_variable_any的 wait 函數可以接受任何lockable參數,而condition_variable只能接受std::unique_lock類型的參數,除此以外,和condition_variable幾乎完全一樣

例如利用互斥量、鎖和條件變量實現生產着消費者問題:

class Buffer{
public:
    Buffer(int nSize = 0):m_read(0),m_nCapacity(nSize){
    }
    void get(int& x){
        {
        boost::shared_lock<shared_mutex> lock(m_mutex);
        while(m_read == 0){
            {
                mutex::scoped_lock guard(io_mutex);
                std::cout<<"empty waiting ..."<<std::endl;
            }
            m_conditionGet.wait(lock);
        }
        x = m_stack.top();
        --m_read;
        m_stack.pop();
        }
        m_conditionPut.notify_one();
    }
    void put(int x){
        {
        boost::unique_lock<shared_mutex> lock(m_mutex);
        while(m_read == m_nCapacity){
            {
                mutex::scoped_lock guard(io_mutex);
                std::cout<<"full waiting ..."<<std::endl;
            }
            m_conditionPut.wait(lock);
        }
        m_stack.push(x);
        ++m_read;
        }
        m_conditionGet.notify_one();
    }
private:
    boost::condition_variable_any m_conditionPut;
    boost::condition_variable_any m_conditionGet;
    boost::shared_mutex           m_mutex;
    int                           m_nCapacity;
    std::stack<int>                    m_stack;
    int                           m_read;
};
Buffer buf(5);
void producer(int n){
    for(int i = 0; i < n; ++i){
        {
            mutex::scoped_lock guard(io_mutex);
            std::cout<<"put: "<<i<<std::endl;
        }
        buf.put(i);
    }
}
void consumer(int n){
    int x = 0;
    for(int i = 0; i < n; ++i){
        buf.get(x);
        mutex::scoped_lock guard(io_mutex);
        std::cout<<"get: "<<x<<std::endl;
    }
}

5. future用來獲取異步任務的結果,因此可以把它當成一種簡單的線程間同步的手段。通過async或packaged_task啓動的方法都可以利用future來獲取任務的執行結果與狀態。注意Future中的get方法會阻塞當前調用者線程直到結果返回。

例如:

int funcDelay(){
    std::cout<<"start delay..."<<std::endl;
    this_thread::sleep(boost::posix_time::millisec(5000));
    std::cout<<"end delay..."<<std::endl;
    return 1;
}
int main(int argc, char *argv[])
{
    unique_future<int> fu = boost::async(funcDelay);

//    this_thread::sleep(boost::posix_time::millisec(6000));

    try{
        fu.get();
    }catch(const std::exception& e){
            std::cout<<e.what()<<std::endl;
    }
    std::cout<<"no delay..."<<std::endl;
    return 0;
}
程序會阻塞主線程,直到get()返回。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章