C++ std::shared_mutex讀寫鎖

0.前言

讀寫鎖把對共享資源的訪問者劃分成讀者和寫者,讀者只對共享資源進行讀訪問,寫者則需要對共享資源進行寫操作。C++17開始,標準庫提供了shared_mutex類(在這之前,可以使用boost的shared_mutex類或系統相關api)。和其他便於獨佔訪問的互斥類型不同,shared_mutex 擁有兩個訪問級別:

  • 共享:多個線程能共享同一互斥的所有權(如配合shared_lock);
  • 獨佔:僅有一個線程能佔有互斥(如配合lock_guard、unique_lock)。

shared_mutex 通常用於多個讀線程能同時訪問同一資源而不導致數據競爭,但只有一個寫線程能訪問的情形。

1.認識std::shared_mutex

通過查看該類的接口(https://zh.cppreference.com/w/cpp/thread/shared_mutex),可以看到,該類除了互斥鎖定接口,還提供了共享鎖定接口。

  • lock() 鎖定互斥。若另一線程已鎖定互斥,則到 lock() 的調用將阻塞執行,直至獲得鎖。可以用 std::lock_guard 和 std::unique_lock 管理互斥鎖定。
  • shared_lock() 獲得互斥的共享所有權。若另一線程以排他性所有權保有互斥,則到 shared_lock() 的調用將阻塞執行,直到能取得共享所有權。若已以任何模式(排他性或共享)佔有 mutex 的線程調用 shared_lock() ,則行爲未定義。若多於實現定義最大數量的共享所有者已以共享模式鎖定互斥,則 shared_lock() 阻塞執行,直至共享所有者的數量減少。所有者的最大數量保證至少爲 10000 。可以用std::shared_lock管理共享鎖定。

2.實例演示

這裏直接借用在線手冊上的例子:

#include <iostream>
//std::unique_lock
#include <mutex> 
#include <shared_mutex>
#include <thread>

class ThreadSafeCounter {
public:
	ThreadSafeCounter() = default;

	// 多個線程/讀者能同時讀計數器的值。
	unsigned int get() const {
		std::shared_lock<std::shared_mutex> lock(mutex_);
		return value_;
	}

	// 只有一個線程/寫者能增加/寫線程的值。
	void increment() {
		std::unique_lock<std::shared_mutex> lock(mutex_);
		value_++;
	}

	// 只有一個線程/寫者能重置/寫線程的值。
	void reset() {
		std::unique_lock<std::shared_mutex> lock(mutex_);
		value_ = 0;
	}

private:
	mutable std::shared_mutex mutex_;
	unsigned int value_ = 0;
};

int main() {
	ThreadSafeCounter counter;

	auto increment_and_print = [&counter]() {
		for (int i = 0; i < 3; i++) {
			counter.increment();
			std::cout << std::this_thread::get_id() << '\t' << counter.get() << std::endl;
		}
	};

	std::thread thread1(increment_and_print);
	std::thread thread2(increment_and_print);

	thread1.join();
	thread2.join();

	system("pause");
	return 0;
}

(本文主要是學習參考手冊上的內容。)

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