亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

C++11?condition_variable條件變量的用法說(shuō)明

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

1 什么是條件變量

condition_variable是一個(gè)類,常和mutex搭配使用。

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

防止多線程場(chǎng)景下,共享變量混亂。

理解條件變量要先理解三個(gè)概念:

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

2 condition_variable類定義

2.1 wait函數(shù)

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

3 condition_variable用法

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

3.1 資源修改線程步驟

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

3.2 資源等待線程步驟

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

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

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

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

4 代碼示例

4.1 無(wú)需notify場(chǎng)景

當(dāng)wait第一次執(zhí)行是,條件已經(jīng)滿足,則程序不會(huì)阻塞(即無(wú)需notify),會(huì)直接向下執(zhí)行。(僅為說(shuō)明3.2 中第2點(diǎn)(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子線程開(kāi)始執(zhí)行"  << endl;
    // Wait until main() sends data
    std::unique_lock<std::mutex> lk(m);
    std::cout << "4、worker_thread子線程獲取到鎖,條件滿足無(wú)需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í)行權(quán)限,主線程執(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、主線程開(kāi)始執(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、主線程條件滿足無(wú)需notify" << endl;
        cv.wait(lk, []{return processed;});
    }
    
    worker.join();
     std::cout << "10、主線程結(jié)束" << endl;
}

執(zhí)行結(jié)果:

4.2 正常應(yīng)用場(chǎng)景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子線程開(kāi)始執(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、主線程開(kāi)始執(zhí)行"  << std::endl;
    data = "Example data";
    // send data to the worker thread
    {
        std::cout << "2、主線程休眠,子線程進(jìn)入執(zhí)行"  << std::endl;
        std::this_thread::sleep_for(std::chrono::milliseconds(1000));
        std::cout << "5、主線程結(jié)束休眠,主線程獲取lk鎖,進(jìn)入執(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í)行時(shí)鐘周期未結(jié)束,繼續(xù)執(zhí)行主線程獲取lk, wait檢查條件不滿足,釋放鎖" << endl;
        std::unique_lock<std::mutex> lk(m);
        cv.wait(lk, []{return processed;});
    }
   
    worker.join();
     std::cout << "11、主線程結(jié)束" << endl;
}

執(zhí)行結(jié)果:

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

同時(shí)4.1也會(huì)因?yàn)閏pu時(shí)鐘周期,執(zhí)行順序有所變動(dòng)。

4.3 正常應(yīng)用場(chǎng)景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子線程開(kāi)始執(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、主線程開(kāi)始執(zhí)行"  << std::endl;
    data = "Example data";
    // send data to the worker thread
    {
        std::cout << "2、主線程休眠,子線程進(jìn)入執(zhí)行"  << std::endl;
        std::this_thread::sleep_for(std::chrono::milliseconds(1000));
        std::cout << "5、主線程結(jié)束休眠,主線程獲取lk鎖,進(jìn)入執(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í)行時(shí)鐘周期未結(jié)束,繼續(xù)執(zhí)行主線程獲取lk, wait檢查條件不滿足,釋放鎖" << endl;
        std::unique_lock<std::mutex> lk(m);
        cv.wait(lk, []{return processed;});
    }
    
    worker.join();
    std::cout << "11、主線程結(jié)束" << endl;
}

執(zhí)行結(jié)果:

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

相關(guān)文章

  • C語(yǔ)言基于graphics.h實(shí)現(xiàn)圣誕樹(shù)

    C語(yǔ)言基于graphics.h實(shí)現(xiàn)圣誕樹(shù)

    這篇文章主要介紹了圣誕樹(shù)代碼,c語(yǔ)言編程,基于graphics.h實(shí)現(xiàn),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-12-12
  • C++小知識(shí):用++i替代i++

    C++小知識(shí):用++i替代i++

    今天小編就為大家分享一篇關(guān)于C++小知識(shí):用++i替代i++,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2019-01-01
  • C語(yǔ)言編寫(xiě)五子棋游戲

    C語(yǔ)言編寫(xiě)五子棋游戲

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言編寫(xiě)五子棋游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-02-02
  • C++實(shí)現(xiàn)Dijkstra算法的示例代碼

    C++實(shí)現(xiàn)Dijkstra算法的示例代碼

    迪杰斯特拉算法(Dijkstra)是由荷蘭計(jì)算機(jī)科學(xué)家狄克斯特拉于1959年提出的,因此又叫狄克斯特拉算法。是從一個(gè)頂點(diǎn)到其余各頂點(diǎn)的最短路徑算法。本文將用C++實(shí)現(xiàn)Dijkstra算法,需要的可以參考一下
    2022-07-07
  • C++二分查找在搜索引擎多文檔求交的應(yīng)用分析

    C++二分查找在搜索引擎多文檔求交的應(yīng)用分析

    這篇文章主要介紹了C++二分查找在搜索引擎多文檔求交的應(yīng)用,實(shí)例分析了二分查找的原理與C++的實(shí)現(xiàn)及應(yīng)用技巧,需要的朋友可以參考下
    2015-06-06
  • C++中#pragma once與#ifndef對(duì)比分析

    C++中#pragma once與#ifndef對(duì)比分析

    當(dāng)我們編寫(xiě)C++代碼時(shí),經(jīng)常需要使用頭文件來(lái)引入一些常用的函數(shù)、類或者變量,如果一個(gè)頭文件被重復(fù)包含,就會(huì)導(dǎo)致編譯錯(cuò)誤或者運(yùn)行時(shí)錯(cuò),為了避免發(fā)生,我們需要使用預(yù)處理指令來(lái)防止頭文件被重復(fù)包含,常用的預(yù)處理指令有#pragma once和#ifndef,需要的朋友可以參考下
    2023-05-05
  • C++實(shí)現(xiàn)學(xué)生信息管理系統(tǒng)(Map實(shí)現(xiàn))

    C++實(shí)現(xiàn)學(xué)生信息管理系統(tǒng)(Map實(shí)現(xiàn))

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)學(xué)生信息管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-06-06
  • c++和python實(shí)現(xiàn)順序查找實(shí)例

    c++和python實(shí)現(xiàn)順序查找實(shí)例

    這篇文章主要介紹了c++和python實(shí)現(xiàn)順序查找實(shí)例,流程即將目標(biāo)數(shù)值和數(shù)據(jù)庫(kù)中的每個(gè)數(shù)值進(jìn)行比較,如果相同則搜索完成,如果不同則繼續(xù)比較下一處,下面來(lái)看看具體的實(shí)例操作吧,需要的朋友可以參考一下
    2022-03-03
  • C++核心編程之內(nèi)存分區(qū)詳解

    C++核心編程之內(nèi)存分區(qū)詳解

    這篇文章主要為大家詳細(xì)介紹了C++核心編程之內(nèi)存分區(qū),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2022-03-03
  • 使用C++調(diào)用Python代碼的方法詳解

    使用C++調(diào)用Python代碼的方法詳解

    這篇文章主要介紹了使用C++調(diào)用Python代碼并給大家介紹了.py和.pyc的區(qū)別,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-02-02

最新評(píng)論