c++ 條件變量

參考cplusplus
參考cppreference

1.condition_variable

  • 為std::unique_lock提供條件變量

1.1 wait/ wait_for / wait_until

//unconditional (1) 
void wait (unique_lock<mutex>& lck);

//predicate (2) 
template <class Predicate>
  void wait (unique_lock<mutex>& lck, Predicate pred);
  • 條件變量工作過程:
    step1.調(diào)用者把鎖住的lck傳給函數(shù),函數(shù)然后自動把線程放到等待條件的線程列表上缕溉,然后對lck進行解鎖寝志。
    step2.一旦條件變量滿足户秤,wait返回時,函數(shù)解除阻塞鹰服,病重新多l(xiāng)ck進行加鎖。
    如果指定了謂詞pred,函數(shù)只在pred為false才阻塞整份,并且通知只有在pred為true的時候才能解除阻塞。
// condition_variable::wait (with predicate)
#include <iostream>           // std::cout
#include <thread>             // std::thread, std::this_thread::yield
#include <mutex>              // std::mutex, std::unique_lock
#include <condition_variable> // std::condition_variable

std::mutex mtx;
std::condition_variable cv;

int cargo = 0;
bool shipment_available() {return cargo!=0;}

void consume (int n) {
  for (int i=0; i<n; ++i) {
    std::unique_lock<std::mutex> lck(mtx);
    cv.wait(lck,shipment_available);
    // consume:
    std::cout << cargo << '\n';
    cargo=0;
  }
}

int main ()
{
  std::thread consumer_thread (consume,10);

  // produce 10 items when needed:
  for (int i=0; i<10; ++i) {
    while (shipment_available()) std::this_thread::yield();
    std::unique_lock<std::mutex> lck(mtx);
    cargo = i+1;
    cv.notify_one();
  }

  consumer_thread.join();

  return 0;
}
//unconditional (1) 
template <class Rep, class Period>
  cv_status wait_for (unique_lock<mutex>& lck,
                      const chrono::duration<Rep,Period>& rel_time);

//predicate (2) 
template <class Rep, class Period, class Predicate>
       bool wait_for (unique_lock<mutex>& lck,
                      const chrono::duration<Rep,Period>& rel_time, Predicate pred);
  • 版本1返回 cv_status::timeout或者cv_status::no_timeout籽孙;
    版本2返回pred()
// condition_variable::wait_for example
#include <iostream>           // std::cout
#include <thread>             // std::thread
#include <chrono>             // std::chrono::seconds
#include <mutex>              // std::mutex, std::unique_lock
#include <condition_variable> // std::condition_variable, std::cv_status

std::condition_variable cv;

int value;

void read_value() {
  std::cin >> value;
  cv.notify_one();
}

int main ()
{
  std::cout << "Please, enter an integer (I'll be printing dots): \n";
  std::thread th (read_value);

  std::mutex mtx;
  std::unique_lock<std::mutex> lck(mtx);
  while (cv.wait_for(lck,std::chrono::seconds(1))==std::cv_status::timeout) {
    std::cout << '.' << std::endl;
  }
  std::cout << "You entered: " << value << '\n';

  th.join();

  return 0;
}
//unconditional (1) 
template <class Clock, class Duration>
  cv_status wait_until (unique_lock<mutex>& lck,
                        const chrono::time_point<Clock,Duration>& abs_time);

//predicate (2) 
template <class Clock, class Duration, class Predicate>
       bool wait_until (unique_lock<mutex>& lck,
                        const chrono::time_point<Clock,Duration>& abs_time,
                        Predicate pred);

1.2 notify_one / notify_all

void notify_one() noexcept;
  • 將等待該條件的一個線程取消阻塞烈评。多余一個線程等待時,選擇哪個線程是未指定的犯建。
// condition_variable::notify_one
#include <iostream>           // std::cout
#include <thread>             // std::thread
#include <mutex>              // std::mutex, std::unique_lock
#include <condition_variable> // std::condition_variable

std::mutex mtx;
std::condition_variable produce,consume;

int cargo = 0;     // shared value by producers and consumers

void consumer () {
  std::unique_lock<std::mutex> lck(mtx);
  while (cargo==0) consume.wait(lck);
  std::cout << cargo << '\n';
  cargo=0;
  produce.notify_one();
}

void producer (int id) {
  std::unique_lock<std::mutex> lck(mtx);
  while (cargo!=0) produce.wait(lck);
  cargo = id;
  consume.notify_one();
}

int main ()
{
  std::thread consumers[10],producers[10];
  // spawn 10 consumers and 10 producers:
  for (int i=0; i<10; ++i) {
    consumers[i] = std::thread(consumer);
    producers[i] = std::thread(producer,i+1);
  }

  // join them back:
  for (int i=0; i<10; ++i) {
    producers[i].join();
    consumers[i].join();
  }

  return 0;
}
void notify_all() noexcept;
// condition_variable::notify_all
#include <iostream>           // std::cout
#include <thread>             // std::thread
#include <mutex>              // std::mutex, std::unique_lock
#include <condition_variable> // std::condition_variable

std::mutex mtx;
std::condition_variable cv;
bool ready = false;

void print_id (int id) {
  std::unique_lock<std::mutex> lck(mtx);
  while (!ready) cv.wait(lck);
  // ...
  std::cout << "thread " << id << '\n';
}

void go() {
  std::unique_lock<std::mutex> lck(mtx);
  ready = true;
  cv.notify_all();
}

int main ()
{
  std::thread threads[10];
  // spawn 10 threads:
  for (int i=0; i<10; ++i)
    threads[i] = std::thread(print_id,i);

  std::cout << "10 threads ready to race...\n";
  go();                       // go!

  for (auto& th : threads) th.join();

  return 0;
}

2.condition_variable_any

  • 為任何的lock類型提供條件變量
//unconditional (1) 
template <class Lock> void wait (Lock& lck);

//predicate (2) 
template <class Lock, class Predicate>
  void wait (Lock& lck, Predicate pred);
// condition_variable_any::notify_all
#include <iostream>           // std::cout
#include <thread>             // std::thread
#include <mutex>              // std::mutex
#include <condition_variable> // std::condition_variable_any

std::mutex mtx;
std::condition_variable_any cv;
bool ready = false;

void print_id (int id) {
  mtx.lock();
  while (!ready) cv.wait(mtx);
  // ...
  std::cout << "thread " << id << '\n';
  mtx.unlock();
}

void go() {
  mtx.lock();
  ready = true;
  cv.notify_all();
  mtx.unlock();
}

int main ()
{
  std::thread threads[10];
  // spawn 10 threads:
  for (int i=0; i<10; ++i)
    threads[i] = std::thread(print_id,i);

  std::cout << "10 threads ready to race...\n";
  go();                       // go!

  for (auto& th : threads) th.join();

  return 0;
}

3.notify_all_at_thread_exit

void notify_all_at_thread_exit (condition_variable& cond, unique_lock<mutex> lck);
  • lck最好是右值
    在線程退出的時候類似于做了一下工作:
lck.unlock();
cond.notify_all()
// notify_all_at_thread_exit
#include <iostream>           // std::cout
#include <thread>             // std::thread
#include <mutex>              // std::mutex, std::unique_lock
#include <condition_variable> // std::condition_variable

std::mutex mtx;
std::condition_variable cv;
bool ready = false;

void print_id (int id) {
  std::unique_lock<std::mutex> lck(mtx);
  while (!ready) cv.wait(lck);
  // ...
  std::cout << "thread " << id << '\n';
}

void go() {
  std::unique_lock<std::mutex> lck(mtx);
  std::notify_all_at_thread_exit(cv,std::move(lck));
  ready = true;
}

int main ()
{
  std::thread threads[10];
  // spawn 10 threads:
  for (int i=0; i<10; ++i)
    threads[i] = std::thread(print_id,i);
  std::cout << "10 threads ready to race...\n";

  std::thread(go).detach();   // go!

  for (auto& th : threads) th.join();

  return 0;
}

4.cv_status——前面有用到

enum class cv_status { no_timeout, timeout };
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末讲冠,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子适瓦,更是在濱河造成了極大的恐慌竿开,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,496評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件玻熙,死亡現(xiàn)場離奇詭異否彩,居然都是意外死亡,警方通過查閱死者的電腦和手機揭芍,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評論 3 392
  • 文/潘曉璐 我一進店門胳搞,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人称杨,你說我怎么就攤上這事肌毅。” “怎么了姑原?”我有些...
    開封第一講書人閱讀 162,632評論 0 353
  • 文/不壞的土叔 我叫張陵悬而,是天一觀的道長。 經(jīng)常有香客問我锭汛,道長笨奠,這世上最難降的妖魔是什么袭蝗? 我笑而不...
    開封第一講書人閱讀 58,180評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮般婆,結(jié)果婚禮上到腥,老公的妹妹穿的比我還像新娘。我一直安慰自己蔚袍,他們只是感情好乡范,可當我...
    茶點故事閱讀 67,198評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著啤咽,像睡著了一般晋辆。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上宇整,一...
    開封第一講書人閱讀 51,165評論 1 299
  • 那天瓶佳,我揣著相機與錄音,去河邊找鬼鳞青。 笑死霸饲,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的盼玄。 我是一名探鬼主播贴彼,決...
    沈念sama閱讀 40,052評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼埃儿!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起融涣,我...
    開封第一講書人閱讀 38,910評論 0 274
  • 序言:老撾萬榮一對情侶失蹤童番,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后威鹿,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體剃斧,經(jīng)...
    沈念sama閱讀 45,324評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,542評論 2 332
  • 正文 我和宋清朗相戀三年忽你,在試婚紗的時候發(fā)現(xiàn)自己被綠了幼东。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,711評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡科雳,死狀恐怖根蟹,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情糟秘,我是刑警寧澤简逮,帶...
    沈念sama閱讀 35,424評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站尿赚,受9級特大地震影響散庶,放射性物質(zhì)發(fā)生泄漏蕉堰。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,017評論 3 326
  • 文/蒙蒙 一悲龟、第九天 我趴在偏房一處隱蔽的房頂上張望屋讶。 院中可真熱鬧,春花似錦须教、人聲如沸丑婿。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽羹奉。三九已至,卻和暖如春约计,著一層夾襖步出監(jiān)牢的瞬間诀拭,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評論 1 269
  • 我被黑心中介騙來泰國打工煤蚌, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留耕挨,地道東北人。 一個月前我還...
    沈念sama閱讀 47,722評論 2 368
  • 正文 我出身青樓尉桩,卻偏偏與公主長得像筒占,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子蜘犁,可洞房花燭夜當晚...
    茶點故事閱讀 44,611評論 2 353

推薦閱讀更多精彩內(nèi)容

  • 接著上節(jié) atomic翰苫,本節(jié)主要介紹condition_varible的內(nèi)容,練習代碼地址这橙。本文參考http://...
    jorion閱讀 8,489評論 0 7
  • <condition_variable > 頭文件主要包含了與條件變量相關(guān)的類和函數(shù)奏窑。相關(guān)的類包括 std::co...
    張霸天閱讀 3,772評論 1 0
  • 本文根據(jù)眾多互聯(lián)網(wǎng)博客內(nèi)容整理后形成,引用內(nèi)容的版權(quán)歸原始作者所有屈扎,僅限于學習研究使用埃唯,不得用于任何商業(yè)用途。 互...
    深紅的眼眸閱讀 1,099評論 0 0
  • 以下是我最近幾個星期學習c++11做的一些記錄鹰晨,包括收集的一些信息墨叛,整理的相關(guān)概念和寫的一些測試代碼。具體相關(guān)代碼...
    在河之簡閱讀 2,805評論 0 6
  • 番客從馬來帶回的“agak”模蜡,漳州地區(qū)等多為“a-kah”漠趁,泉州地區(qū)有讀為“a-lah”,廈門等也有讀較像原本音讀...
    毋成囝閱讀 400評論 1 2