C++條件變量


1.作用:在C++11中,我們可以使用條件變量(std::condition_variable)實現多個線程間的同步操作;當條件不滿足時,相關線程被一直阻塞,並釋放CPU,直到某種條件出現,這些線程才會被喚醒。條件變量需要和互斥量(鎖)一起搭配使用。

用在多線程中。

線程A:等待一個條件滿足

線程B:專門在消息隊列中扔消息,線程B觸發了這個條件,A就滿足條件了,可以繼續執行

2.常用的成員函數:

  (1)wait():阻塞當前線程,直到條件變量被喚醒。

  (2)wait_for:阻塞當前線程,直到條件變量被喚醒或到達指定時長后。

  (3)wait_until:阻塞當前線程,直到條件變量被喚醒,或知道抵達指定的時間點。

  (4)notify_once:通知一個等待的線程。

  (5)notify_all:通知所有等待的線程。

3.范例代碼

#include <iostream>
#include<thread>
#include<string>
#include<vector>
#include<algorithm>
#include<windows.h>
#include<list>
#include<mutex>

using namespace std;

class myClass
{
public:
    void AddOrder()
    {
        for (int i = 0; i < 10000; i++)
        {
            cout << "addOrder執行,插入一個元素" << i << endl;
            std::unique_lock<std::mutex> sbGuard(m_mutex);
            m_orderList.push_back(i);

            //我們嘗試把wait()的線程喚醒,
            //注意:如果其他線程在wait時,調用notify_one,可以喚醒,但是當其他線程沒有在wait時,執行的notify_one沒有用
            m_Cond.notify_one();    

        }
    }

    void RemoveOrder()
    {
        int command;
        while (true)
        {
            std::unique_lock<std::mutex> sbGuard(m_mutex);
            //如果第二個參數lambda表達式返回值是true,那么wait()直接返回;
            //如果第二個闡述lambda表達式返回值是false,那么wait()將解鎖互斥量,並阻塞到本行,
            //那么阻塞到什么時候為止呢,阻塞到其他某個線程調用notify_once()成員函數為止;
            //如果wait()沒有第二個參數:m_Cond.wait(sbGuard),那么就跟第二個參數lambda表達式返回false效果一樣,
            //當其他線程用notify_once()將本wait(原來是阻塞狀態)喚醒,wait就開始回復工作,wait不斷的嘗試重新獲取互斥量鎖
            //    (a)如果拿不到鎖,它會不斷嘗試取獲取
            //    (b)如果獲取到鎖后:
            //        (b.1):拿到鎖,如果wait有第二個參數,就判斷這個lambda表達式,如果lambda表達式為false,那么wait又對互斥量鎖解鎖又開始阻塞
            //        (b.2):如果lambda表達式為true,則wait返回,流程往下走
            //       (b.3):如果wait沒有第二個參數,則wait返回,流程往下走
            m_Cond.wait(sbGuard, [this] {             //一個lambda就是一個可調用對象(函數)
                if (!m_orderList.empty())
                    return true;
                return false;
            });

            command = m_orderList.front();    // 返回m_orderList第一個元素
            m_orderList.pop_front();        //移除m_orderList第一個元素
            sbGuard.unlock();           //unique_lock靈活,可以隨時解鎖,以免鎖住太長時間

            cout << "RemoveOrder取出一個元素" << command << endl;

            //其他任務
        }
    }

private:
    std::list<int> m_orderList;
    std::mutex m_mutex;
    std::condition_variable m_Cond;    //生成一個條件變量對象
};

int main()
{
    myClass my;

    std::thread obj1(&myClass::AddOrder, &my);
    std::thread obj2(&myClass::RemoveOrder, &my);
    obj1.join();
    obj2.join();

    system("pause");
}
View Code

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM