c++11 執行緒間同步---利用std::condition_variable實現

拾荒荒發表於2021-07-08

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;
}

除錯結果

相關文章