目录

1.前言

2.正文

3.代码和验证

1.前言:

前几日上班时,因为底层逻辑修改。多线程情况下,许多函数如果依然按照原有的锁去串行执行,效率会很低。(原先是 std::mutex ,以及每个函数用的锁是std::lock_guard)

这时我的领导给我新任务,修改多线程的锁,在修改后,要求函数 1 函数2 要能并发执行,且前两者并发执行时与函数 3 函数4 函数5是互斥的。而函数 3,4,5与所有函数都互斥。(例如函数3运行的时候,函数1 2 4 5都是卡着等待函数3执行完毕再继续执行)。

我实在是不会做,这个时候请教我领导,他告诉我用读写锁就能解决问题。c++读写锁的应用也就是使用 shared_mutex,shared_lock,这两者者解决问题。

这是本人对此次经历的记录,可能写的并不太好。可以参考他人文章和cppRefrecne官方文章。

C++多线程——读写锁shared_lock/shared_mutex_princeteng的博客-CSDN博客_shared_lock

std::shared_lock - cppreference.com

2.正文:关于shared_mutex,shared_lock的知识和描述

shared_mutex 类是一个同步原语,可用于保护共享数据不被多个线程同时访问。与便于独占访问的其他互斥类型不同,shared_mutex 拥有二个访问级别:

  • 共享 - 多个线程能共享同一互斥的所有权。
  • 独占性 - 仅一个线程能占有互斥。

若一个线程已获取独占性锁(通过 lock 、 try_lock ),则无其他线程能获取该锁(包括共享的)。

仅当任何线程均未获取独占性锁时,共享锁能被多个线程获取(通过 lock_shared 、 try_lock_shared )。

在一个线程内,同一时刻只能获取一个锁(共享独占性)。

共享互斥体在能由任何数量的线程同时读共享数据,但一个线程只能在无其他线程同时读写时写同一数据时特别有用。

shared_mutex 类满足共享互斥体 (SharedMutex) 和标准布局类型 (StandardLayoutType) 的所有要求。

以上是cppreferenced的原文。翻译一遍就是这样的逻辑

当Mutex是shared_mutex 的时候

1.当有函数使用共享锁时,能够与其他享有共享锁的函数也能并发同步执行。而和所有独占锁的函数是互斥的。

2.当有一个函数使用独占锁时,其他所有的用同一个Mutex带锁的函数都是与其互斥的。

那么这个情况就和我所遇到的需求是完全一致的。

已知的独占锁

lock

锁定互斥,若互斥不可用则阻塞
(公开成员函数)

try_lock

尝试锁定互斥,若互斥不可用则返回
(公开成员函数)

unlock

解锁互斥
(公开成员函数)                
std::unique_lock 自动加锁和解锁
std::lock_guard 自动加锁和解锁

已知的共享锁

共享锁定

lock_shared

为共享所有权锁定互斥,若互斥不可用则阻塞
(公开成员函数)

try_lock_shared

尝试为共享所有权锁定互斥,若互斥不可用则返回
(公开成员函数)

unlock_shared

解锁互斥(共享所有权)
(公开成员函数)
std::shared_lock 自动加锁和解锁

3.代码验证

以下代码是本人在vs2019,c++最新标准下运行的。

可以直接复制过去看效果,也可以自己稍作修改进行验证

#include <iostream>
#include <string>
#include <mutex>
#include <thread>
#include <shared_mutex>
#include <Windows.h>std::shared_mutex g_sMutex;void writeTime(const std::string funName ,int time) {for (size_t i = 1; i < time; i++) {std::string outPut = funName + ":" + std::to_string(time);std::cout << outPut << std::endl;Sleep(1000);}
}void shared_1(int seconds) {std::shared_lock<std::shared_mutex> theLock(g_sMutex);writeTime("shared_1" , seconds);
}void shared_2(int seconds) {std::shared_lock<std::shared_mutex> theLock(g_sMutex);writeTime("shared_2", seconds);
}void unique_1(int seconds) {std::unique_lock<std::shared_mutex> lck(g_sMutex);writeTime("unique_1", seconds);
}void unique_2(int seconds) {std::unique_lock<std::shared_mutex> lck(g_sMutex);writeTime("unique_2", seconds);
}void nomralSuo(int seconds) {std::lock_guard<std::shared_mutex> lck(g_sMutex);writeTime("nomralSuo", seconds);
}int main()
{std::vector<std::thread> vecThread;vecThread.push_back(std::thread(nomralSuo, 10));vecThread.push_back(std::thread(shared_1, 10));vecThread.push_back(std::thread(shared_2, 10));vecThread.push_back(std::thread(unique_1, 10));vecThread.push_back(std::thread(unique_2, 10));for (auto & oneThread : vecThread){oneThread.join();}
}

c++ 并发-读写锁(shared_mutex,shared_lock)相关推荐

  1. C++并发型模式#7: 读写锁 - shared_mutex

    本文转载自C++并发型模式#7: 读写锁 - shared_mutex,作者是邓作恒,其博客地址为:http://dengzuoheng.github.io/ 读者-写者问题 考虑有一块共享内存, 外 ...

  2. 对变量移位顺序读写_Java多线程并发读写锁ReadWriteLock实现原理剖析

    关于读写锁 Java语法层面的synchronized锁和JDK内置可重入锁ReentrantLock我们都经常会使用,这两种锁都属于纯粹的独占锁,也就是说这些锁任意时刻只能由一个线程持有,其它线程都 ...

  3. Java并发- 读写锁中的性能之王:StampedLock

    为什么StampedLock这么神奇?能够达到这种效果,它的核心思想在于,在读的时候如果发生了写,应该通过重试的方式来获取新的值,而不应该阻塞写操作.这种模式也就是典型的无锁编程思想,和CAS自旋的思 ...

  4. Java 并发 —— 读写锁(ReadWriteLock)

    读写锁(ReadWriteLock),顾名思义,就是在读写某文件时,对该文件上锁. 1. ReentrantReadWriteLock 三部曲: 加锁: 读写操作: 解锁:(为保证解锁操作一定执行,通 ...

  5. C++多线程快速入门(四)shared_mutex以及读写锁应用

    在前面的三讲中我们使用的mutex都是普通的std::mutex,这里介绍一下shared_mutex,版本为C++17 std::shared_mutex的底层实现时操作系统提供的读写锁,在读多写少 ...

  6. Boost读写锁:shared_mutex

    shared_mutex即读写锁,不同与我们常用的独占式锁mutex,shared_mutex是共享与独占共存的锁,实现了读写锁的机制,即多个读线程一个写线程,通常用于对于一个共享区域的读操作比较频繁 ...

  7. C++ std::shared_mutex读写锁

    0.前言 读写锁把对共享资源的访问者划分成读者和写者,读者只对共享资源进行读访问,写者则需要对共享资源进行写操作.C++17开始,标准库提供了shared_mutex类(在这之前,可以使用boost的 ...

  8. golang:1.并发编程之互斥锁、读写锁详解

    本文转载自junjie,而后稍作修改. 一.互斥锁 互斥锁是传统的并发程序对共享资源进行访问控制的主要手段.它由标准库代码包sync中的Mutex结构体类型代表.sync.Mutex类型(确切地说,是 ...

  9. 死磕Java并发:J.U.C之读写锁:ReentrantReadWriteLock

    作者:chenssy 来源:http://cmsblogs.com/?p=2213 重入锁ReentrantLock是排他锁,排他锁在同一时刻仅有一个线程可以进行访问,但是在大多数场景下,大部分时间都 ...

最新文章

  1. 汇编寄存器(内存访问)基础知识之三---mov指令
  2. CVPR2019接收结果公布了,但CVPR 2018的那些论文都怎么样了?
  3. 又见斐波那契数列(矩阵构造+矩阵快速幂)
  4. PHP 简单计算器代码实现
  5. mysql slave lock 跳过_slave开启MTS时执行mysqldump引发死锁案例
  6. ubuntu codeblocks10.05安装全过程 (包含注意事项:安装后不能启动)
  7. 13款宝马x5质量到底怎么样_新款宝马X5和奔驰GLE450谁更强?
  8. android 编译 sdl,SDL编译 - Android本地视频播放器开发_Linux编程_Linux公社-Linux系统门户网站...
  9. 使用GDB调试产生多进程的程序
  10. 企业用好大数据只需这6招
  11. 【GNN】一份简短入门《图神经网络GNN》笔记小册
  12. 吃了核辐射食物怎么办_不瞒你说:经常胃酸烧心怎么办?,多吃这些食物,保护胃黏膜远...
  13. 微信开发者工具测试方法
  14. MobaXterm复制黏贴快捷键
  15. 如何在WordPress中显示链接的实时预览
  16. wps分享为什么要登入_靠谱租分享:为什么要在年前租办公室
  17. 赋能型生态演化路径与六大竞争制高点——保险科技生态建设...
  18. kernel_neon_begin
  19. firefox_config
  20. 基于vs插件的abp代码生成器

热门文章

  1. Numpy 函数解释:numpy.random.normal()
  2. 基于51单片机驱动MPU6050模块(LCD1602显示)
  3. Themida WinLicense免费下载脱壳使用教程功能介绍大全
  4. 喵帕斯之矩阵 SDUT
  5. 轮式机器人算法仿真的一些杂七杂八02
  6. API 设计、开发、测试一体化协作平台ApiFox、ApiPost和YAPI对比
  7. Atmel Studio-SAM单片机开发 ---EXTINT
  8. Locust的学习笔记(一、环境搭建以及初识locust)
  9. mysql 单表最多能存多少数据?
  10. 分治法解决计算凸包问题