C++并发与多线程-使用读写锁

使用读写锁的好处是所有的读操作都能同时进行,而写操作需要独占互斥量。这样能保证读操作不会相互阻塞等待。而他们的共同竞争者是那些独占互斥量的写操作。标准模板库中提供了std::shared_lock(共享锁)和std::shared_mutex(共享互斥量)。而阅读源码可以看到,shared_lock再构造的时候其实调用互斥量的lock_shared()函数。

template
class shared_lock
{	// shareable lock
public:
	typedef _Mutex mutex_type;

	shared_lock() noexcept
		: _Pmtx(nullptr), _Owns(false)
		{	// default construct
		}

	explicit shared_lock(mutex_type& _Mtx)
		: _Pmtx(_STD addressof(_Mtx)), _Owns(true)
		{	// construct with mutex and lock shared
		_Mtx.lock_shared();        //此处调用了互斥量的lock_shared()函数。
		}

    //等等。
    //.........
}

而只有std::shared_mutex提供了lock_shared()函数。因此我们需要定义我们的互斥量为std::shared_mutex, 读操作的锁为std::shared_lock lk(_lock);  而写操作的锁为 std::unique_lock lk(_lock);  因为写操作要独占互斥量,因此使用std::unique_lock。提供以下代码作为参考:

//thread_safe_counter.h文件。

#pragma once
#include 

class thread_safe_counter {
public:
	thread_safe_counter() : _value(0) {}
	int read_value() const;
	void write_value(int value);
private:
	mutable std::shared_mutex _lock;
	int _value;
};
//thread_safe_counter.cpp 文件。

#include "pch.h"
#include "thread_safe_counter.h"
#include 

int thread_safe_counter::read_value() const
{
	std::shared_lock lk(_lock);
	std::cout << "读取线程拿到了共享锁: thread_id : " << std::this_thread::get_id() << std::endl;
	std::this_thread::sleep_for(std::chrono::seconds(2));
	std::cout << "读取线程执行了2秒: thread_id : " << std::this_thread::get_id() << std::endl;
	return _value;
}

void thread_safe_counter::write_value(int value)
{
	std::unique_lock lk(_lock);
	std::cout << "写入线程拿到了共享锁: thread_id : " << std::this_thread::get_id() << std::endl;
	std::this_thread::sleep_for(std::chrono::seconds(3));
	std::cout << "写入线程执行了3秒: thread_id : " << std::this_thread::get_id() << std::endl;
	_value = value;
}
//main函数文件。

#include "pch.h"
#include 
#include 
#include 
#include 
#include "thread_safe_counter.h"


int main()
{
	thread_safe_counter couter;
	std::vector vecs;
	for (int i = 0; i < 5; i++) {
		std::thread a(&thread_safe_counter::read_value, &couter);
		vecs.push_back(std::move(a));
	}

	std::thread b(&thread_safe_counter::write_value, &couter, 2);

	for (int i = 0; i < 5; i++) {
		vecs[i].join();
	}
	b.join();
	return 0;
}

定义了5个读线程和1个写线程。运行结果如下, 读线程同时进行,因为使用了std::shared_lock lk(_lock)。而读线程差不多执行2秒,所有读线程执行完之后,写线程才拿到互斥量。可以看到先执行的读线程再所有读线程中不一定是先执行完的。

C++并发与多线程-使用读写锁_第1张图片

你可能感兴趣的:(C++并发与多线程)