C++多线程之读写锁

1. 定义数据结构

  • readers:当前持有读锁的线程数。
  • waitWriters:等待写锁的线程数(用于写优先策略)。
  • writing:标记是否有写锁被持有。
  • 互斥锁和条件变量mutexcondition_variable

2. 读锁逻辑

  • 加锁:
    • 加锁条件:没有写锁被持有且没有写线程在等待(写优先)。
    • 增加 readers 计数。
  • 解锁:
    • 减少 readers 计数。
    • 若所有读锁释放,唤醒一个等待的写线程。

3. 写锁逻辑

  • 加锁:
    • 增加 waitWriters 计数。
    • 加锁条件:没有读锁和写锁被持有。
    • 减少 waitWriters 计数,标记 writing 为 true。
  • 解锁:
    • 标记 writing 为 false。
    • 若还有等待的写线程就唤醒一个写线程;否则唤醒所有的读线程

```cpp
#include<iostream>
#include<mutex>
#include<thread>
#include<condition_variable>
using namespace std;

class ReadWriteLock
{
public:
	ReadWriteLock():readers(0),writing(false), waitWriters(0){}
	void readLock()
	{
		unique_lock<mutex> lock(mtx);
		read_cv.wait(lock, [this]() {return !writing && waitWriters == 0; });
		readers++;
	}
	void readUnlock()
	{
		unique_lock<mutex> lock(mtx);
		if(--readers == 0)
			write_cv.notify_one();
	}
	void writeLock()
	{
		unique_lock<mutex> lock(mtx);
		waitWriters++;
		write_cv.wait(lock, [this]() {return readers == 0 && writing == false; });
		waitWriters--;
		writing = true;
	}
	void writeUnlock()
	{
		unique_lock<mutex> lock(mtx);
		writing = false;
		if (waitWriters > 0)
		{
			write_cv.notify_one();
		}
		else read_cv.notify_all();
	}
private:
	int readers;
	int waitWriters;
	bool writing;
	mutex mtx;
	condition_variable read_cv;
	condition_variable write_cv;
};

// 测试

static int data_ = 0;
ReadWriteLock rw_lock;
// 读取data的值
void reader()
{
	rw_lock.readLock();
	cout << "读取 data_ = " << data_ << endl;
	rw_lock.readUnlock();
}

// 增加data的值
void writer()
{
	rw_lock.writeLock();
	data_++;
	cout << "写入后 data_ = " << data_ << endl;
	rw_lock.writeUnlock();
}

int main()
{
	thread r1(reader);
	thread w1(writer);
	thread w2(writer);
	thread r2(reader);
	r1.join();
	w1.join();
	w2.join();
	r2.join();
}
补充知识点:

1、unique_lock可以换成lock_guard吗?
答:不可以,wait()函数需要一个unique_lock,因为它需要暂时释放锁,等待条件变量通知后再重新获取锁。如果换成lock_guard不能在wait期间释放锁会导致死锁,因为其他线程无法获得锁来通知条件变量。
2、wait()用法

// 版本1:无谓词
void wait(std::unique_lock<std::mutex>& lock);

// 版本2:带谓词(常用)
template <class Predicate>
void wait(std::unique_lock<std::mutex>& lock, Predicate pred);

在 wait() 内部,每次线程被唤醒时(无论是通过 notify 还是虚假唤醒),都会调用 pred()。
只有当 pred() 返回 true 时,wait() 才会返回,否则继续等待。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

是不是应该好好学习呢?

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值