1. 程式人生 > >理解多執行緒(三)--互斥量

理解多執行緒(三)--互斥量

std::mutex

mutex就是互斥量的意思,在c++中使用互斥量需要包含#include

引入互斥量

之前瞭解了執行緒訪問公有資料是不安全的,所以使用互斥量來防治執行緒不安全的操作。
互斥量就是一個變數,只有兩種狀態,加鎖和解鎖。每一個互斥量管理一個公有資料,一個執行緒訪問公有資料後,互斥量加鎖,其他執行緒就不能訪問,等待之前的執行緒訪問完成解鎖後,才能訪問。

mutex分類

Mutex 系列類(四種)
std::mutex,基本Mutex 類。
std::recursive_mutex,遞迴 Mutex 類。
std::time_mutex,定時基本Mutex 類。
std::recursive_timed_mutex,定時遞迴 Mutex 類。

std::mutex

構造:不允許拷貝構造和move構造,初始化為解鎖狀態。
成員函式:
lock():加鎖,如果已經被其他執行緒加鎖了,則會阻塞
unlock():解鎖,線上程沒有獲得鎖是不能進行解鎖
try_lock():嘗試加鎖,如果已經被其他執行緒加鎖了,則不會阻塞,返回false。

mutex  mu;
int x{ 0 }; 
mu.lock();
x++;
mu.unlock();

std::recursive_mutex

std::mutex只能進行一次上鎖解鎖操作,std::recursive_mutex允許一個執行緒對一個互斥量多次上鎖,但解鎖次數也必須相同。

recursive_mutex  mu;
int x{ 0 }; 
mu.lock();mu.lock();
x++;
mu.unlock();mu.unlock();

std::timed_mutex

try_lock_for():
新增的成員函式,嘗試一直阻塞一個時間段加鎖,如果超過這個時間段沒有獲得鎖則返回false
try_lock_until():
新增的成員函式,嘗試在一個時間點前加鎖,如果這個時間段沒有獲得鎖則會返回false

  recursive_mutex  mu;
int x{ 0 }; 
		if (mu.try_lock_for(std::chrono:
:microseconds(10))) //嘗試阻塞10秒加鎖 { ++counter; mu.unlock(); //解鎖 }

自動加鎖

上面的都是手動進行加鎖和解鎖,但有時如果人們加鎖後忘記了瞭解鎖,就會造成死鎖,所以c++11封裝了上面的加鎖解鎖操作,製作了std::lock_guard 與 std::unique_lock來進行自動的加鎖和解鎖操作。

std::lock_guard

std::lock_guard 在建構函式中進行加鎖,解構函式中進行解鎖。所以我們可以在棧上建立std::lock_guard,在生命週期結束後,自動解鎖。

int x {0 }; //原子變數
mutex mu; //互斥量
void fun()
{
	std::lock_guard<std::mutex> lock(mu);
	this_thread::sleep_for(std::chrono::microseconds(100));
	x++;
}
int main()
{
	for (size_t i = 0; i < 100; i++)
	{
		std::thread(fun).detach();
	}
	this_thread::sleep_for(std::chrono::microseconds(5000));
	cout << x << endl;
	system("pause");
	return 0;
}

std::unique_lock

std::unique_lock比std::lock_guard功能更加強大,但是會耗費更多的時間和空間。