新闻中心

c++怎么使用std::shared_mutex实现读写锁_c++读写锁shared_mutex用法详解

2025-10-29
浏览次数:
返回列表
std::shared_mutex是C++17引入的读写锁机制,允许多个线程共享读锁、单个线程独占写锁,适用于读多写少场景,需包含头文件并启用C++17,推荐使用std::shared_lock和std::unique_lock进行RAII管理以确保异常安全和防止死锁。

c++怎么使用std::shared_mutex实现读写锁_c++读写锁shared_mutex用法详解

std::shared_mutex 是 C++17 引入的一个同步原语,用于实现高效的读写锁机制。它允许多个线程同时进行读操作(共享访问),但在写操作(独占访问)时只允许一个线程执行,并且会阻塞所有其他读和写线程。这种机制非常适合“读多写少”的场景,比如缓存、配置管理等。

1. std::shared_mutex 基本概念

std::shared_mutex 区分两种锁定模式:
  • 共享锁(shared lock):多个线程可以同时持有,适用于读操作。
  • 独占锁(exclusive lock):仅一个线程能持有,适用于写操作。
当有线程持有共享锁时,新的共享锁可以立即获得;但独占锁必须等待所有共享锁释放后才能获取。

2. 头文件与编译要求

使用 std::shared_mutex 需要包含头文件:

#include <shared_mutex></shared_mutex>

Pinokio Pinokio

Pinokio是一款开源的AI浏览器,可以安装运行各种AI模型和应用

Pinokio 232 查看详情 Pinokio 并且编译器需支持 C++17 或更高版本。例如用 g++ 编译时加上:

g++ -std=c++17 your_file.cpp

3. 使用方法示例

下面是一个典型的读写锁使用示例:

#include <iostream>
#include <thread>
#include <vector>
#include <shared_mutex>
#include <chrono>

std::vector<int> data = {1, 2, 3};
std::shared_mutex shm;  // 共享互斥量

// 读操作函数
void reader(int id) {
    shm.lock_shared();  // 获取共享锁
    std::cout << "Reader " << id << " sees data: ";
    for (int d : data) {
        std::cout << d << " ";
    }
    std::cout << "\n";
    std::this_thread::sleep_for(std::chrono::milliseconds(100)); // 模拟处理时间
    shm.unlock_shared();  // 释放共享锁
}

// 写操作函数
void writer(int id) {
    shm.lock();  // 获取独占锁
    std::cout << "Writer " << id << " is writing...\n";
    data.push_back(id);
    std::this_thread::sleep_for(std::chrono::milliseconds(200));
    std::cout << "Writer " << id << " finished writing.\n";
    shm.unlock();  // 释放独占锁
}

主函数中启动多个读线程和写线程:

int main() {
    std::vector<std::thread> threads;

    // 启动 5 个读线程
    for (int i = 1; i <= 5; ++i) {
        threads.emplace_back(reader, i);
    }

    // 启动 2 个写线程
    for (int i = 10; i <= 11; ++i) {
        threads.emplace_back(writer, i);
    }

    // 启动更多读线程
    for (int i = 6; i <= 10; ++i) {
        threads.emplace_back(reader, i);
    }

    // 等待所有线程完成
    for (auto& t : threads) {
        t.join();
    }

    return 0;
}

输出可能类似(顺序不固定):

Reader 1 sees data: 1 2 3 Reader 2 sees data: 1 2 3 ... Writer 10 is writing... Writer 10 finished writing. Reader 6 sees data: 1 2 3 10 ...

4. 推荐使用 RAII 管理锁

直接调用 lock/unlock 容易出错,建议使用 RAII 封装类自动管理锁的生命周期:
  • std::shared_lock<:shared_mutex>:用于管理共享锁。
  • std::unique_lock<:shared_mutex>:也可用于独占锁,但更常用的是直接用 lock_guard 或 unique_lock 配合普通 mutex。不过 shared_mutex 支持 unique_lock 的独占模式。
改写上面的函数更安全的方式:

void reader(int id) {
    std::shared_lock<std::shared_mutex> lock(shm);  // 自动加共享锁,析构时释放
    std::cout << "Reader " << id << " sees data: ";
    for (int d : data) {
        std::cout << d << " ";
    }
    std::cout << "\n";
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}  // lock 在这里自动释放

void writer(int id) {
    std::unique_lock<std::shared_mutex> lock(shm);  // 独占锁
    std::cout << "Writer " << id << " is writing...\n";
    data.push_back(id);
    std::this_thread::sleep_for(std::chrono::milliseconds(200));
    std::cout << "Writer " << id << " finished writing.\n";
}  // lock 析构时自动释放

这种方式避免了忘记 unlock 导致死锁的风险,也支持异常安全。

5. 注意事项与最佳实践

使用 std::shared_mutex 时注意以下几点:
  • 确保读写操作逻辑正确区分:只读用 shared_lock,修改用 unique_lock 或 lock()。
  • 避免长时间持有共享锁,否则会阻塞写线程,造成写饥饿。
  • 某些平台实现中,shared_mutex 性能开销比普通 mutex 高,应根据实际场景选择是否使用。
  • 不能递归加锁:同一个线程重复对 shared_mutex 加共享或独占锁会导致未定义行为。
基本上就这些。合理使用 std::shared_mutex 能有效提升多线程程序在读密集场景下的并发性能。

以上就是c++++怎么使用std::shared_mutex实现读写锁_c++读写锁shared_mutex用法详解的详细内容,更多请关注其它相关文章!


# 头文件  # 有机肥营销推广方案  # 小白建设网站视频  # 青岛网站建设游戏文案  # 政府网站建设要求自查  # 汉中seo整合营销  # 太原短视频seo研发  # seo通过网络渠道传播  # 网站建设越秀  # 义乌seo哪家专业  # 网站推广公司流程图制作  # 是一个  # 的是  # ai  # 推荐使用  # 多线程  # 游戏开发  # 适用于  # 死锁  # 多个  # 递归  # red  # stream  # ios  # c++ 


相关栏目: 【 科技资讯46185 】 【 网络学院92790


相关推荐: Bilibili动漫最新防封地址发布-Bilibili动漫2025年最稳正版入口推荐  蛙漫官方正版入口 蛙漫网页在线全集免费观看  Pandas DataFrame 高效批量赋值:告别循环与笛卡尔积误区  如何使用Rector自动化升级旧代码_通过Composer安装和配置Rector进行代码重构  快手官方唯一登录入口 谨防山寨钓鱼网站  Python中如何避免重复条件判断:利用数据结构实现动态逻辑  Gmail邮箱申请注册直达_Gmail邮箱免费注册PC版官网入口2025  拼多多赚钱渠道_拼多多收益来源  实现分段式页面滚动导航:CSS与J*aScript教程  C++如何使用AddressSanitizer(ASan)_C++调试工具中检测内存访问错误的利器  汽水音乐在线版入口_汽水音乐网页播放手册  AO3最新入口2025公告_AO3中文官网合集  抖音网页版平台入口 抖音网页版官网在线访问教程  win11 arm版怎么安装 M1/M2 Mac虚拟机安装ARM win11的方法  QQ邮箱网页版入口登录 QQ邮箱在线邮箱官方通道  俄罗斯Yandex免登录入口_Yandex搜索引擎官网一键直达  优化MinIO list_objects_v2 操作的性能瓶颈与最佳实践  曝R星经典之作开发图 设计简陋但信息密集!  J*aScript中针对特定容器内图片动画的实现教程  小猿搜题在线学习页面在哪_小猿搜题在线学习中心入口  j*a toString()的覆盖  怎么在浏览器上运行HTML文件_浏览器运行HTML文件技巧【技巧】  Steam官网入口直达 Steam注册及登录步骤  win11如何卸载Windows更新补丁 Win11解决更新导致系统不稳定的问题【修复】  Lar*el表单中优雅地处理“返回”按钮以规避验证:最佳实践指南  提升屏幕阅读器对“m”时间单位的播报准确性:HTML与CSS组合解决方案  Django模型中自动计算可用余额的实现方法  2026春节假期时间安排 2026春节假日查询  Archive of Our Own官网直达 AO3最新可用地址一览  mysql密码锁定怎么解锁_mysql密码锁定解锁后修改密码步骤  J*aScript Promise链中如何正确终止后续.then执行并处理错误  Go语言中对Map值调用带指针接收者方法:原理与最佳实践  J*aScript实现单选按钮与关联输入框的联动禁用教程  Windows电脑怎么截图最方便_系统自带截图工具的5种神仙用法【技巧】  微信语音通话掉线如何解决 微信语音通话稳定优化方法  在J*a中如何开发在线活动报名与管理系统_活动报名管理项目实战解析  蛙漫移动版在线看 蛙漫手机浏览器直达入口  C++ explicit关键字防止隐式转换_C++构造函数安全规范  sublime如何配置Python开发环境_将sublime打造成轻量级Python IDE  铁路12306的积分有效期是多久_铁路12306积分有效期说明  163邮箱注册官网 免费申请163个人邮箱  在J*a中如何在J*a中使用异常机制记录错误日志_异常日志实践经验  C++如何进行游戏物理模拟_使用Box2D库为C++游戏添加2D物理效果  Win10双系统截图高效法 截屏快捷键速记【技巧】  QQ邮箱登录官网首页 腾讯QQ邮箱网页入口  谷歌浏览器如何快速清除某个网站的数据_Chrome网站缓存清理方法  动漫花园资源网使用步骤_动漫花园资源网下载流程  在Go语言中利用后缀数组处理多字符串:实现高效文本匹配与自动补全  AWS EC2实例间SQL Server连接超时:安全组配置与故障排除指南  SteamMachine定价或为699美元 大家想入手吗? 

搜索