c++多线程库手册学习笔记(三)

本文介绍了C++中的unique_lock管理类,强调其灵活性,并对比lock_guard。接着详细讲解了shared_lock和shared_mutex,阐述了读写锁的概念,特别是读线程和写线程之间的互斥关系。提到了读友好型和写友好型读写锁的区别,并指出C++标准库实现的读写锁为读友好型。最后,预告了关于写友好型读写锁的进一步探讨。
摘要由CSDN通过智能技术生成

(承接上一篇)
3、更自由一些的mutex管理类:unique_lock
这个管理类在设计的时候考虑的更多的是使用锁的自由度,

  • 具有lock_guard的所有功能,
  • 而且提供随时lock和unlock的能力,效率上应该比lock_guard有所缺乏。
    在设计时感觉参考了unique_ptr的思想,
  • 可以将管理类与mutex锁解关联,
std::mutex m;
std::unique_lock lk(m); //获取锁并lock
//or
std::unique_lock lk(m,std::defer_lock); //关联锁,先不要lock(待会自己手动lock)
//or
std::unique_lock lk(m,std::adopt_lock); //关联锁,不要再lock(用于关联前已经lock了锁)

unique_lock其实没什么好说的地方,跳了

4、shared_lock
说到这个锁管理类,就得说一下另一种mutex了,叫shared_mutex。
shared_mutex实际上是一种读写锁,对共享数据进行并发读时,实际上可以多个线程一块访问,只有写操作时需要提供互斥的环境。

对于读写锁,当没有写线程访问时,读线程可以同时访问共享数据,也就是读线程之间是不互斥的。而有写线程访问时,其他的读线程和其他的写线程都将被block,以保护共享数据的完整性。

所以读/写线程的代码通常是这样的:

std::shared_mutex m;
void read()
{
	std::shared_lock lk(m);
	read_shared_data();
}
void write()
{
	std::lock_guard lk(m);
	write_shared_data();
}

题外话
读写锁的性能一般和并发性能息息相关,一般有这么两种读写锁:

  • 读友好型读写锁
  • 写友好型读写锁

第一种读写锁的特点是,写线程必须在所有读线程都放弃锁的情况下才能对数据进行修改。这种锁的问题其实稍加分析就显而易见,如果很多读线程不断地交叠式的读数据,那么写线程可能要一直等待而得不到锁去更新数据。

第二种读写锁的特点是,当有写线程准备写数据时,出了当前已经开始读取的读线程外,其余新来的读线程都会被阻塞,直到所有正在读的读线程都完成任务后,写线程进入修改数据,然后再放行所有读线程。

经过测试,c++实现的是第一种读写锁,但其实我个人觉得第二种读写锁的用途会大一些,因为当数据要进行更改时,一般说明原有数据可能已经过时,这个时候过时的数据被读走的意义也许就不是很大了。

明天有时间更新一下写友好型的读写锁设计,以及linux内核中的一种【强·写友好型】读写锁,那种读写锁的基本设计思想是,只要有写线程要写,写线程可以立马进行数据的修改,不管有没有正在读的读线程(当然依然与其他写线程互斥),由读线程读完之后检测,如果自己在读的过程中有写操作发生,则读线程自觉重读。

以下附c++读写锁类型测试:
代码
代码
代码结果

可以看到10ms时,写线程企图获取锁,但由于读线程源源不断交叠访问,所以直到最后读线程都结束了,55ms时写线程才拿到锁。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值