c++ 并发-读写锁(shared_mutex,shared_lock)

目录

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();
    }
}

  • 7
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值