C++併發(條件變量)

C++標準庫對條件變量有兩套實現:std::condition_variable和std::condition_variable_any,其中std::condition_variable_any的通用性更強,但是佔用系統資源更多。std::condition_variable需要搭配std::unique_lock使用。
首先介紹如何使用std::condition_variable:
案例1:條件變量condition_variable的使用

#include <mutex> //std::mutex std::lock_guard
#include <condition_variable> //std::condition_variable
std::mutex mut;  //互斥量
std::queue<data_chunk> data_queue;  //隊列
std::conditon_variable data_cond;  //條件變量

void data_prparation_thread()
{
	while(more_data_to_prepare())
	{
		data_chunk const data = prepare_data();  //獲取數據
		std::lock_guard<std::mutex> lk(mut);  //鎖管理器
		data_queue.push(data);  //數據寫隊列
		data_cond.notify_one();  //通知等待線程
	}
}

void data_processing_thread()
{
	while(true)
	{
		std::unique_lock<std::mutex> lk(mut);
		data_cond.wait(lk, []{return !data_queue.empty();});//條件變量會首先判斷隊列是否爲空,若爲空則進行阻塞,等待通知。得到通知後,會再次判斷隊列是否爲空,若不爲空纔會獲取鎖纔會接觸阻塞,獲取鎖並進行後續程序。
		data_chunk data = data_queue.front();
		data_queue.pop();
		lk.unlock();
		process(data);
		if (is_last_chunk(data))
			break;
	}
}

上述代碼有兩部分內容:一是數據準備線程,每次運行都會往隊列裏面添加元素並且通知數據處理線程;另一個是數據處理線程,在數據處理完之前一直循環運行,獲取數據-等待通知-獲取數據,按照這樣的規律進行。

案列2:

#include <mutex> //std::mutex std::lock_guard
#include <condition_variable> //std::condition_variable
bool ready = false;
std::mutex mut;  //互斥量
std::conditon_variable data_cond;  //條件變量

void process_thread1()  //等待線程1
{
	std::unique_lock<std::mutex> lk(mut);
	data_cond.wait(lk, ready);
	lk.unlock();
	process1();
}

void process_thread2()  //等待線程2
{
	std::unique_lock<std::mutex> lk(mut);
	data.cond.wait(lk, ready);
	lk.unlock();
	process2();
}

void data_init_thread()  //通知線程
{
	std::lock_guard<std::mutex> lk(mut);
	ready = true;
	data_cond.notify_all();
}

上述代碼中共有三個線程,等待線程1、等待線程2和等待線程3。等待線程1和等待線程2會阻塞,等待通知線程的通知纔會繼續運行。

案例三:有超時功能的條件變量

#include <mutex>
#include <condition_variable>
#include <chrono>

std::condition_variable cv;
bool done;
std::mutex m;

bool wait_loop()
{
	auto const timeout = std::chrono::steady_clock::now() + std::chrono::milliseconds(500); //設置超時時間點
	std::unique_lock<std::mutex> lk(m);
	while(!done)
	{
		if(cv.wait_until(lk, timeout)==std::cv_status::timeout)//當超過某個時間點timeout時還無法獲得鎖,則會返回狀態值std::cv_status::timeout。還有一種std::condition_variable::wait_for(lk, duar)則是超過了時間段duar還無法獲得鎖就會返回狀態值
			break;
	}
	return done;
}

條件變量實例cv會一直等待互斥量,直到超時

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章