最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++11?condition_variable條件變量的用法說明

 更新時間:2022年07月11日 15:03:04   作者:kingforyang  
這篇文章主要介紹了C++11?condition_variable條件變量的用法說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

1 什么是條件變量

condition_variable是一個類,常和mutex搭配使用。

condition_variable類是一個同步原語,可用于阻塞一個線程或同時阻止多個線程,直到另一個線程修改共享變量并通知condition_variable。

防止多線程場景下,共享變量混亂。

理解條件變量要先理解三個概念:

  • 鎖 (鎖住共享變量,線程獨占)
  • wait 等待 (等待通知條件變量,變化的共享變量是否滿足條件)
  • notify 通知 (通知等待的條件變量,共享變量發(fā)送變化)

2 condition_variable類定義

2.1 wait函數(shù)

void wait( std::unique_lockstd::mutex& lock );
//Predicate是lambda表達式。
template< class Predicate >
void wait( std::unique_lockstd::mutex& lock, Predicate pred );
//以上二者都被notify_one())或notify_broadcast()喚醒,但是
//第二種方式是喚醒后也要滿足Predicate的條件。
//如果不滿足條件,繼續(xù)解鎖互斥量,然后讓線程處于阻塞或等待狀態(tài)。
//第二種等價于
while (!pred())
{
wait(lock);
}

3 condition_variable用法

condition_variable必定至少有兩方,一方是資源修改線程,一方是資源等待線程。就跟打籃球一樣,同時籃球只會在一個人手中,投籃后就釋放了籃球所有權,其他方就會搶奪籃球所有權。

3.1 資源修改線程步驟

  • 獲取一個mutex使用 std::unique_lock< std::mutex >
  • 保持鎖定狀態(tài),修改共享變量
  • condition_variable對象執(zhí)行notify_one或者notify_all(notify_one/notify_all執(zhí)行前可以釋放鎖)

3.2 資源等待線程步驟

  • 獲取一個mutex使用 std::unique_lock< std::mutex > unlock用于保護要修改的共享變量
  • 檢查條件變量,

(1)條件變量滿足,線程繼續(xù)執(zhí)行

(2)條件變量不滿足,wait會釋放unlock鎖,并掛起線程。

  • 當notify通知條件變量、超時過期或發(fā)生虛假喚醒時,線程被喚醒,互斥鎖unlock被原子地重新獲取。然后,線程應該檢查條件,如果喚醒是假的,則繼續(xù)等待

4 代碼示例

4.1 無需notify場景

當wait第一次執(zhí)行是,條件已經(jīng)滿足,則程序不會阻塞(即無需notify),會直接向下執(zhí)行。(僅為說明3.2 中第2點(1)的情況)

#include <iostream>
#include <string>
#include <thread>
#include <mutex>
#include <condition_variable>
using namespace std;
std::mutex m;
std::condition_variable cv;
std::string data;
bool ready = false;
bool processed = false;
 
void worker_thread()
{
    std::cout << "3、worker_thread子線程開始執(zhí)行"  << endl;
    // Wait until main() sends data
    std::unique_lock<std::mutex> lk(m);
    std::cout << "4、worker_thread子線程獲取到鎖,條件滿足無需notify,不阻塞向下執(zhí)行"  << endl;
    cv.wait(lk, []{return ready;});
 
    // after the wait, we own the lock.
    data += " after processing";
    // Send data back to main()
    processed = true;
    std::cout << "5、Worker thread signals data processing completed\n";
 
    // Manual unlocking is done before notifying, to avoid waking up
    // the waiting thread only to block again (see notify_one for details)
    lk.unlock();
    std::cout << "6、worker_thread子線程交出執(zhí)行權限,主線程執(zhí)行"  << endl;
    std::this_thread::sleep_for(std::chrono::milliseconds(2000));
    
    cv.notify_one();
    std::cout << "9、worker_thread調(diào)用 notify_one"  << endl;
}
int main()
{
    std::thread worker(worker_thread);
    std::cout << "1、主線程開始執(zhí)行"  << std::endl;
    data = "Example data";
    // send data to the worker thread
    {
        //std::this_thread::sleep_for(std::chrono::milliseconds(1000));
        std::lock_guard<std::mutex> lk(m);
        ready = true;
    }
    std::cout << "2、鎖已經(jīng)釋放了,主線程休眠,子線程執(zhí)行"  << std::endl;
    std::this_thread::sleep_for(std::chrono::milliseconds(1000));
    //cv.notify_one();
    {
        std::cout << "7、主線程data:" << data << endl;
        std::unique_lock<std::mutex> lk(m);
        std::cout << "8、主線程條件滿足無需notify" << endl;
        cv.wait(lk, []{return processed;});
    }
    
    worker.join();
     std::cout << "10、主線程結束" << endl;
}

執(zhí)行結果:

4.2 正常應用場景1

#include <iostream>
#include <string>
#include <thread>
#include <mutex>
#include <condition_variable>
using namespace std;
std::mutex m;
std::condition_variable cv;
std::string data;
bool ready = false;
bool processed = false;
 
void worker_thread()
{
    std::cout << "3、worker_thread子線程開始執(zhí)行"  << endl;
    // Wait until main() sends data
    std::unique_lock<std::mutex> lk(m);
    std::cout << "4、worker_thread子線程獲取到鎖,條件不滿足,釋放lk鎖,子線程阻塞"  << endl;
    cv.wait(lk, []{return ready;});
    std::cout << "8、worker_thread子線程獲取到鎖,子線程繼續(xù)執(zhí)行"  << endl;
    // after the wait, we own the lock.
    data += " after processing";
    // Send data back to main()
    processed = true;
    std::cout << "9、Worker thread signals data processing completed\n";
 
    // Manual unlocking is done before notifying, to avoid waking up
    // the waiting thread only to block again (see notify_one for details)
    lk.unlock();
    std::this_thread::sleep_for(std::chrono::milliseconds(5000));
    std::cout << "10、worker_thread調(diào)用 notify_one通知主線程執(zhí)行"  << endl;
    cv.notify_one();
}
int main()
{
    std::thread worker(worker_thread);
    std::cout << "1、主線程開始執(zhí)行"  << std::endl;
    data = "Example data";
    // send data to the worker thread
    {
        std::cout << "2、主線程休眠,子線程進入執(zhí)行"  << std::endl;
        std::this_thread::sleep_for(std::chrono::milliseconds(1000));
        std::cout << "5、主線程結束休眠,主線程獲取lk鎖,進入執(zhí)行"  << std::endl;
        std::lock_guard<std::mutex> lk(m);
        ready = true;
        
    }
    std::cout << "6、主線程釋放lk,調(diào)用notify通知子線程"  << std::endl;
    cv.notify_one();
    {
        std::cout << "7、由于主線程的執(zhí)行時鐘周期未結束,繼續(xù)執(zhí)行主線程獲取lk, wait檢查條件不滿足,釋放鎖" << endl;
        std::unique_lock<std::mutex> lk(m);
        cv.wait(lk, []{return processed;});
    }
   
    worker.join();
     std::cout << "11、主線程結束" << endl;
}

執(zhí)行結果:

這里notify執(zhí)行后不一定立即執(zhí)行子線程,如果cpu執(zhí)行時鐘周期未結束,則主線程會繼續(xù)執(zhí)行. 所以7,8,9,10順序可能變化參見4.3

同時4.1也會因為cpu時鐘周期,執(zhí)行順序有所變動。

4.3 正常應用場景2

#include <iostream>
#include <string>
#include <thread>
#include <mutex>
#include <condition_variable>
using namespace std;
std::mutex m;
std::condition_variable cv;
std::string data;
bool ready = false;
bool processed = false;
 
void worker_thread()
{
    std::cout << "3、worker_thread子線程開始執(zhí)行"  << endl;
    // Wait until main() sends data
    std::unique_lock<std::mutex> lk(m);
    std::cout << "4、worker_thread子線程獲取到鎖,條件不滿足,釋放lk鎖,子線程阻塞"  << endl;
    cv.wait(lk, []{return ready;});
    std::cout << "8、worker_thread子線程獲取到鎖,子線程繼續(xù)執(zhí)行"  << endl;
    // after the wait, we own the lock.
    data += " after processing";
    // Send data back to main()
    processed = true;
    std::cout << "9、Worker thread signals data processing completed\n";
 
    // Manual unlocking is done before notifying, to avoid waking up
    // the waiting thread only to block again (see notify_one for details)
    lk.unlock();
    std::cout << "10、worker_thread調(diào)用 notify_one通知主線程執(zhí)行"  << endl;
    cv.notify_one();
}
int main()
{
    std::thread worker(worker_thread);
    std::cout << "1、主線程開始執(zhí)行"  << std::endl;
    data = "Example data";
    // send data to the worker thread
    {
        std::cout << "2、主線程休眠,子線程進入執(zhí)行"  << std::endl;
        std::this_thread::sleep_for(std::chrono::milliseconds(1000));
        std::cout << "5、主線程結束休眠,主線程獲取lk鎖,進入執(zhí)行"  << std::endl;
        std::lock_guard<std::mutex> lk(m);
        ready = true;
        
    }
    std::cout << "6、主線程釋放lk,調(diào)用notify通知子線程"  << std::endl;
    cv.notify_one();
    {
        for(int i = 0; i< 10000000; i++)
        {
            int j = i;
        }
        std::cout << "7、由于主線程的執(zhí)行時鐘周期未結束,繼續(xù)執(zhí)行主線程獲取lk, wait檢查條件不滿足,釋放鎖" << endl;
        std::unique_lock<std::mutex> lk(m);
        cv.wait(lk, []{return processed;});
    }
    
    worker.join();
    std::cout << "11、主線程結束" << endl;
}

執(zhí)行結果:

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。 

相關文章

  • 詳解NSString 與C++ string字符串的互轉(zhuǎn)

    詳解NSString 與C++ string字符串的互轉(zhuǎn)

    這篇文章主要介紹了詳解NSString 與C++ string字符串的互轉(zhuǎn)的相關資料,需要的朋友可以參考下
    2017-07-07
  • 淺談VS中添加頭文件時顯示無法找到文件的問題

    淺談VS中添加頭文件時顯示無法找到文件的問題

    下面小編就為大家?guī)硪黄獪\談VS中添加頭文件時顯示無法找到文件的問題。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-01-01
  • Qt實現(xiàn)拖拽功能圖文教程(支持拖放文件、拖放操作)

    Qt實現(xiàn)拖拽功能圖文教程(支持拖放文件、拖放操作)

    這篇文章主要給大家介紹了關于Qt實現(xiàn)拖拽功能(支持拖放文件、拖放操作)的相關資料,Qt是一款多平臺的C++應用程序開發(fā)框架,它的獨特之處在于可以快速開發(fā)出拖放式的開發(fā)桌面程序,需要的朋友可以參考下
    2023-11-11
  • vs2022項目文件夾內(nèi).vs文件夾容量虛高問題的解決

    vs2022項目文件夾內(nèi).vs文件夾容量虛高問題的解決

    經(jīng)常會發(fā)現(xiàn)VS的項目文件夾占用空間很大,本文主要介紹了vs2022項目文件夾內(nèi).vs文件夾容量虛高問題的解決,具有一定的參考價值,感興趣的可以了解一下
    2023-09-09
  • C語言打印楊輝三角示例匯總

    C語言打印楊輝三角示例匯總

    本文給大家匯總了2種使用C語言實現(xiàn)楊輝三角的方法,不過還是給大家推薦第一種,希望大家能夠喜歡。
    2016-02-02
  • C++中using的三種用法舉例詳解

    C++中using的三種用法舉例詳解

    最近在使用中,發(fā)現(xiàn)了一種以前沒學過的using用法,于是在這里,將using的幾種用法總結一下,下面這篇文章主要給大家介紹了關于C++中using的三種用法,需要的朋友可以參考下
    2023-02-02
  • C語言實現(xiàn)惡作劇關機程序

    C語言實現(xiàn)惡作劇關機程序

    大家好,本篇文章主要講的是C語言實現(xiàn)惡作劇關機程序,感興趣的同學趕快來看一看吧,對你有幫助的話記得收藏一下
    2022-01-01
  • C++使用文件實現(xiàn)學生信息管理系統(tǒng)

    C++使用文件實現(xiàn)學生信息管理系統(tǒng)

    這篇文章主要為大家詳細介紹了C++使用文件實現(xiàn)學生信息管理系統(tǒng),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-01-01
  • C語言實現(xiàn)停車場項目

    C語言實現(xiàn)停車場項目

    這篇文章主要為大家詳細介紹了C語言實現(xiàn)停車場項目,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • C++仿函數(shù)的概念優(yōu)點和使用

    C++仿函數(shù)的概念優(yōu)點和使用

    這篇文章主要介紹了C++仿函數(shù)的概念優(yōu)點和使用,在C++中,仿函數(shù)是指重載了operator的類或結構體的對象,它們的行為類似于普通函數(shù),因此可以像函數(shù)一樣被調(diào)用,需要的朋友可以參考下
    2025-04-04

最新評論

贡嘎县| 区。| 金堂县| 天镇县| 北宁市| 略阳县| 阳泉市| 沁水县| 开远市| 苏州市| 衡东县| 从化市| 桑植县| 汤原县| 伽师县| 呼图壁县| 高雄市| 姚安县| 偏关县| 东台市| 松江区| 湾仔区| 伊金霍洛旗| 太原市| 安仁县| 黔江区| 鹤岗市| 达孜县| 徐水县| 广饶县| 岱山县| 霍山县| 罗源县| 凤庆县| 宝兴县| 丰台区| 华蓥市| 武平县| 米林县| 新乡市| 平利县|