c++11 線程間同步—利用std::condition_variable實現

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

調試結果

Tags: