<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
condition_variable是一個類,常和mutex搭配使用。
condition_variable類是一個同步原語,可用於阻塞一個執行緒或同時阻止多個執行緒,直到另一個執行緒修改共用變數並通知condition_variable。
防止多執行緒場景下,共用變數混亂。
理解條件變數要先理解三個概念:
wait
等待 (等待通知條件變數,變化的共用變數是否滿足條件)notify
通知 (通知等待的條件變數,共用變數傳送變化)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的條件。 //如果不滿足條件,繼續解鎖互斥量,然後讓執行緒處於阻塞或等待狀態。 //第二種等價於 while (!pred()) { wait(lock); }
condition_variable必定至少有兩方,一方是資源修改執行緒,一方是資源等待執行緒。就跟打籃球一樣,同時籃球只會在一個人手中,投籃後就釋放了籃球所有權,其他方就會搶奪籃球所有權。
(1)條件變數滿足,執行緒繼續執行
(2)條件變數不滿足,wait會釋放unlock鎖,並掛起執行緒。
當wait第一次執行是,條件已經滿足,則程式不會阻塞(即無需notify),會直接向下執行。(僅為說明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子執行緒開始執行" << endl; // Wait until main() sends data std::unique_lock<std::mutex> lk(m); std::cout << "4、worker_thread子執行緒獲取到鎖,條件滿足無需notify,不阻塞向下執行" << 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 completedn"; // 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子執行緒交出執行許可權,主執行緒執行" << endl; std::this_thread::sleep_for(std::chrono::milliseconds(2000)); cv.notify_one(); std::cout << "9、worker_thread呼叫 notify_one" << endl; } int main() { std::thread worker(worker_thread); std::cout << "1、主執行緒開始執行" << 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、鎖已經釋放了,主執行緒休眠,子執行緒執行" << 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; }
執行結果:
#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子執行緒開始執行" << 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子執行緒獲取到鎖,子執行緒繼續執行" << 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 completedn"; // 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呼叫 notify_one通知主執行緒執行" << endl; cv.notify_one(); } int main() { std::thread worker(worker_thread); std::cout << "1、主執行緒開始執行" << std::endl; data = "Example data"; // send data to the worker thread { std::cout << "2、主執行緒休眠,子執行緒進入執行" << std::endl; std::this_thread::sleep_for(std::chrono::milliseconds(1000)); std::cout << "5、主執行緒結束休眠,主執行緒獲取lk鎖,進入執行" << std::endl; std::lock_guard<std::mutex> lk(m); ready = true; } std::cout << "6、主執行緒釋放lk,呼叫notify通知子執行緒" << std::endl; cv.notify_one(); { std::cout << "7、由於主執行緒的執行時鐘週期未結束,繼續執行主執行緒獲取lk, wait檢查條件不滿足,釋放鎖" << endl; std::unique_lock<std::mutex> lk(m); cv.wait(lk, []{return processed;}); } worker.join(); std::cout << "11、主執行緒結束" << endl; }
執行結果:
這裡notify執行後不一定立即執行子執行緒,如果cpu執行時鐘週期未結束,則主執行緒會繼續執行. 所以7,8,9,10順序可能變化參見4.3
同時4.1也會因為cpu時鐘週期,執行順序有所變動。
#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子執行緒開始執行" << 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子執行緒獲取到鎖,子執行緒繼續執行" << 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 completedn"; // 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呼叫 notify_one通知主執行緒執行" << endl; cv.notify_one(); } int main() { std::thread worker(worker_thread); std::cout << "1、主執行緒開始執行" << std::endl; data = "Example data"; // send data to the worker thread { std::cout << "2、主執行緒休眠,子執行緒進入執行" << std::endl; std::this_thread::sleep_for(std::chrono::milliseconds(1000)); std::cout << "5、主執行緒結束休眠,主執行緒獲取lk鎖,進入執行" << std::endl; std::lock_guard<std::mutex> lk(m); ready = true; } std::cout << "6、主執行緒釋放lk,呼叫notify通知子執行緒" << std::endl; cv.notify_one(); { for(int i = 0; i< 10000000; i++) { int j = i; } std::cout << "7、由於主執行緒的執行時鐘週期未結束,繼續執行主執行緒獲取lk, wait檢查條件不滿足,釋放鎖" << endl; std::unique_lock<std::mutex> lk(m); cv.wait(lk, []{return processed;}); } worker.join(); std::cout << "11、主執行緒結束" << endl; }
執行結果:
以上為個人經驗,希望能給大家一個參考,也希望大家多多支援it145.com。
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45