1.前言
很多時候,我們在寫程式的時候,多多少少會遇到下面種需求
一個產品的大致部分流程,由工廠生產,然後放入倉庫,最後由銷售員提單賣出去這樣。
在實際中,倉庫的容量的有限的,也就是說,工廠不能一直生產產品,如果生產太多就會導致倉庫滿了沒地方存放。
為了達到生產效率最大化,就會這樣做,只要倉庫空了一點位置,工廠就開始生產,等倉庫滿了以後,工廠就停止生產。
在這過程中,工廠生產產品的速度是銷售部賣出產品的速度快很多的。
回到程式設計中,工廠就是一個單獨子執行緒, 銷售部也是一個單獨子執行緒
要想模擬達到上邊想要的需求,這就需要用執行緒間同步啦。
情形1
情形2
情形3
2.準備工作
演示環境 | 解決方式 |
---|---|
vs2017 | c++11 條件變數 |
執行緒間同步機制,有很多的實現方式,這裡採用了條件變數的方式。
c++11 把執行緒thread新增到了標準庫,我們可以很方便的使用多執行緒和進行移植。
只需要引入thread標頭檔案即可使用。
#include <thread>
此次我們需要用到的標頭檔案
#include <iostream>
#include <atomic>
#include <thread> /*執行緒類*/
#include <condition_variable> /*條件變數*/
#include <mutex> /*執行緒鎖*/
前提: 在使用 std::condition_variable 時,需要配合 mutex 來使用std::unique_lock進行上鎖/解鎖。
3.程式碼演示
#include <iostream>
#include <thread>
#include <atomic>
#include <condition_variable>
#include <mutex>
std::mutex _mutex; /*執行緒鎖*/
std::condition_variable cv; /*條件變數*/
std::atomic_int productCnt = 0; /*公共變數,產品庫存數量*/
std::atomic_bool isReady = false; /*公共變數,防止假性喚醒執行緒*/
/*生產產品*/
void Fun1()
{
while (true)
{
std::unique_lock<std::mutex> lock(_mutex);
std::cout << "+++生產了產品, 庫存剩餘:" << ++productCnt << std::endl;
isReady = true; /*產品生產好了*/
cv.notify_all(); /*喚醒執行緒,通知Fun2()產品可以賣了*/
cv.wait(lock); /*睡眠執行緒,Fun1()在等待Fun2()把產品賣出去再生產*/
}
}
/*銷售產品*/
void Fun2()
{
while (true)
{
std::unique_lock<std::mutex> lock(_mutex);
/*Fun1()產品還沒生產好,Fun2()在這睡大覺*/
if (!isReady) {
cv.wait(lock);
}
std::cout << "---賣出了產品, 庫存剩餘:" << --productCnt << std::endl;
isReady = false;/*Fun2()把產品買出去啦*/
cv.notify_all();/*Fun2()告訴Fun1()產品已經賣了,可以繼續生產了*/
}
}
/*主函式*/
int main(int argc, char **argv)
{
std::thread t1(Fun1);/*宣告執行緒1*/
std::thread t2(Fun2);/*宣告執行緒2*/
t1.join();/*開啟執行緒1*/
t2.join();/*開啟執行緒2*/
return 0;
}
除錯結果