std::unique_lock

  • std::unique_lock() noexcept; //可以構造一個空的std::unique_lock對象,此時並不擁有任何mutex

  • explicit std::unique_lock (mutex_type& m);//擁有mutex,並調用mutex.lock()對其上鎖

  • std::unique_lock (mutex_type& m, try_to_lock_t tag);//tag=try_lock表示調用mutex.try_lock()嘗試加鎖

  • std::unique_lock (mutex_type& m, defer_lock_t tag) noexcept;//tag=defer_lock表示不對mutex加鎖,只管理mutex,此時mutex應該是沒有加鎖的

  • std::unique_lock (mutex_type& m, adopt_lock_t tag);//tag=adopt_lock表示mutex在此之前已經被上鎖,此時unique_locl管理mutex

  • template <class Rep, class Period>
    std::unique_lock (mutex_type& m, const chrono::duration<Rep,Period>& rel_time);//在一段時間rel_time內嘗試對mutex加鎖,mutex.try_lock_for(rel_time)

  • template <class Clock, class Duration>
    std::unique_lock (mutex_type& m, const chrono::time_point<Clock,Duration>& abs_time);//mutex.try_lock_until(abs_time)直到abs_time嘗試加鎖

  • std::unique_lock (const std::unique_lock&) = delete;//禁止拷貝構造

  • std::unique_lock (std::unique_lock&& x);//獲得x管理的mutex,此後x不再和mutex相關,x此後相當於一個默認構造的std::unique_lock,移動構造函數,具備移動語義,movable but not copyable

c++11多線程中的condition_variable(條件變量) - A_Bo的博客 - CSDN博客

https://blog.csdn.net/li1615882553/article/details/86179781

wait函數

當前線程調用wait()後將被阻塞並且函數會 解鎖 互斥量,如果使用lock_guard則不能調用unlock函數,所以這裏只能使用unique_lock對象,直到另外某個線程調用notify_one或者notify_all喚醒當前線程;一旦當前線程獲得通知(notify),wait()函數也是自動調用lock(),同理不能使用lock_guard對象。

如果wait沒有第二個參數,第一次調用默認條件不成立,直接解鎖互斥量並阻塞到本行,直到某一個線程調用notify_onenotify_all爲止,被喚醒後,wait重新嘗試獲取互斥量,如果得不到,線程會卡在這裏,直到獲取到互斥量,然後無條件地繼續進行後面的操作

如果wait包含第二個參數,如果第二個參數不滿足,那麼wait將解鎖互斥量並堵塞到本行,直到某一個線程調用notify_onenotify_all爲止,被喚醒後,wait重新嘗試獲取互斥量,如果得不到,線程會卡在這裏,直到獲取到互斥量,然後繼續判斷第二個參數,如果表達式爲false,wait對互斥量解鎖,然後休眠,如果爲true,則進行後面的操作

- 1


#include <iostream>
#include <condition_variable>
#include <mutex>
#include <thread>

std::mutex mutex_;
std::condition_variable condVar;


void tStart()
{
	std::cout << "Wait 1" << std::endl;
	std::unique_lock<std::mutex> lock(mutex_);	// 2 進入後,會對mutex_進行加鎖
	
	std::cout << "Enter 1" << std::endl;

	std::this_thread::sleep_for(std::chrono::milliseconds(5000));

	std::cout << "endSleep 1" << std::endl;

	condVar.wait(lock);		// 4 等待的時候,會釋放mutex_


	std::this_thread::sleep_for(std::chrono::milliseconds(5000));	// 7 被喚醒後,則搶佔,進行休眠

	std::cout << "Exit 1" << std::endl;	// 8退出
	
}

void tWait()
{
	std::this_thread::sleep_for(std::chrono::milliseconds(500));	// 1 讓tStart 先進
	std::cout << "Wait 2" << std::endl;

	std::unique_lock<std::mutex> lock(mutex_);	// 3 第2步加鎖後,則會在此等待

	std::cout << "Enter 2" << std::endl;	// 5 在第4步釋放後,則立即進入,並對mutex_加鎖

	std::this_thread::sleep_for(std::chrono::milliseconds(5000));

	std::cout << "Enter 2" << std::endl;

	condVar.notify_one();	// 6 喚醒等待的線程,也只有一個線程在等待
}


int main()
{
	std::thread   threadStart(tStart);
	std::thread	threadWait(tWait);

	threadStart.join();
	threadWait.join();

	return 0;
}


運行結果 :


Wait 1
Enter 1
Wait 2
endSleep 1
Enter 2
Enter 2
Exit 1

- 2




#include <iostream>
#include <condition_variable>
#include <mutex>
#include <thread>

std::mutex mutex_;
std::condition_variable condVar;


bool dataReady;

void waitingForWork() 
{
	std::cout << "Waiting for waitingForWork." << std::endl;

	std::unique_lock<std::mutex> lck(mutex_);	// 2. 對mutex_加鎖

	std::cout << "Enter  A" << std::endl;
	std::this_thread::sleep_for(std::chrono::milliseconds(2000));

	std::cout << "Waiting...." << std::endl;

	condVar.wait(lck, [] {return dataReady; });	// 3. 等待, 釋放mutex_

	std::cout << "Waiting End" << std::endl;	// 6.一直往下執行
	std::cout << "->Processing shared data." << std::endl; 
	std::this_thread::sleep_for(std::chrono::milliseconds(2000));
	std::cout << "Work done." << std::endl;
}

void setDataReady() 
{
	std::this_thread::sleep_for(std::chrono::milliseconds(500));	// 1. 讓 waitingForWork 線程先進
	std::cout << " Waiting for setDataReady." << std::endl;

	std::lock_guard<std::mutex> lck(mutex_);

	std::cout << "Enter  B" << std::endl;	// 4 進入,並對mutex_加鎖, 並一直往下執行
	std::this_thread::sleep_for(std::chrono::milliseconds(2000));

	std::cout << " dataReady = true; " << std::endl;
	dataReady = true;
	std::this_thread::sleep_for(std::chrono::milliseconds(2000));
	std::cout << "Sender: Data is ready." << std::endl;
	std::this_thread::sleep_for(std::chrono::milliseconds(2000));
	condVar.notify_one();	// 5. 喚醒,並結束此線程,釋放mutex_
}

int main() {

	std::cout << std::endl;

	std::thread t1(waitingForWork);
	std::thread t2(setDataReady);

	t1.join();
	t2.join();

	std::cout << std::endl;
	return 0;
}



運行結果 :


Waiting for waitingForWork.
Enter  A
 Waiting for setDataReady.
Waiting....
Enter  B
 dataReady = true;
Sender: Data is ready.
Waiting End
->Processing shared data.
Work done.
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章