0

0

C++中的std::shared_mutex怎么实现读写锁?(允许多读单写的并发控制)

尼克

尼克

发布时间:2026-01-14 15:47:18

|

347人浏览过

|

来源于php中文网

原创

c++kquote>std::shared_mutex是C++17引入的读写锁,需配合std::shared_lock(读)和std::unique_lock(写)使用,不可直接调用lock()/unlock(),且不兼容std::lock_guard。

c++中的std::shared_mutex怎么实现读写锁?(允许多读单写的并发控制)

std::shared_mutex 是 C++17 引入的读写锁,但不能直接构造使用

它本身不提供 lock() / unlock() 这类裸接口,必须配合 std::shared_lock(读锁)和 std::unique_lock(写锁)才能生效。常见错误是试图像 std::mutex 那样直接调用 mtx.lock() —— 这会编译失败,因为 std::shared_mutex 没有这些成员函数。

  • std::shared_lock<:shared_mutex>:用于共享读访问,允许多个线程同时持有
  • std::unique_lock<:shared_mutex>:用于独占写访问,阻塞其他所有读/写操作
  • 注意:C++17 起才支持;C++14 及更早版本需用第三方库(如 Boost.Thread)或自实现

正确加读锁和写锁的写法示例

读操作必须用 std::shared_lock,写操作必须用 std::unique_lock(或 std::lock_guard 的写法仅限于独占语义,但 std::lock_guard 不支持 std::shared_mutex 的共享模式,所以只能用 std::unique_lock)。

#include 
#include 
#include 

std::shared_mutex rw_mtx;
int data = 0;

void reader() {
    std::shared_lock lock(rw_mtx); // ✅ 正确:共享读锁
    // ... 读取 data
}

void writer() {
    std::unique_lock lock(rw_mtx); // ✅ 正确:独占写锁
    ++data;
}
  • 不能用 std::lock_guard<:shared_mutex>:编译报错,该模板不接受 std::shared_mutex
  • 不能对同一 std::shared_mutex 同时持有一个 std::shared_lock 和一个 std::unique_lock:写锁会阻塞新读锁获取,已持有的读锁也会被写锁等待者阻塞直到全部释放
  • 推荐显式指定模板参数,避免依赖 CTAD(C++17 起支持,但某些旧编译器或严格模式下可能推导失败)

性能与兼容性要注意的几个现实问题

不同标准库实现对 std::shared_mutex 的底层策略差异很大,直接影响吞吐和公平性。

简篇AI排版
简篇AI排版

AI排版工具,上传图文素材,秒出专业效果!

下载
  • libstdc++(GCC):在 Linux 上通常基于 futex 实现,但早期版本(如 GCC 7~9)的 std::shared_mutex 性能较差,存在写饥饿风险(大量读锁导致写锁长期无法获取)
  • libc++(Clang / macOS):实现更成熟,读写锁切换开销较低,但 macOS 10.15+ 才完整支持 C++17 线程设施
  • Windows MSVC:从 VS 2015 Update 3 起支持,底层映射到 SRWLock,性能较好,但要注意调试模式下锁竞争检测可能误报
  • 若需跨平台且高负载,建议压测实测;低延迟场景慎用,因共享锁的 acquire/release 开销仍高于普通 mutex

容易忽略的生命周期和异常安全细节

std::shared_lockstd::unique_lock 都是 RAII 类型,但它们的移动语义和可重用性常被误用。

立即学习C++免费学习笔记(深入)”;

  • std::shared_lock 支持移动、可多次 lock()/unlock(),但不能在已锁定状态下再次 lock()(会抛 std::system_error
  • std::unique_lock 同理,且支持延迟锁定(构造时不加锁,后续调用 lock()
  • 不要把锁对象返回或长期保存:锁的生命周期应严格绑定于临界区作用域;跨函数传递锁对象易引发死锁或提前释放
  • 异常发生时 RAII 自动释放,这点安全;但若在临界区内抛异常且未捕获,需确保数据处于一致状态——锁解决并发,不解决逻辑一致性
实际用的时候,最麻烦的往往不是语法,而是读多写少场景下写线程被饿死,或者多个 shared_lock 在嵌套调用中意外延长了读锁持有时间。别只盯着“能编译”,得看运行时行为。

相关专题

更多
硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

1017

2023.10.19

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

62

2025.10.17

php8.4实现接口限流的教程
php8.4实现接口限流的教程

PHP8.4本身不内置限流功能,需借助Redis(令牌桶)或Swoole(漏桶)实现;文件锁因I/O瓶颈、无跨机共享、秒级精度等缺陷不适用高并发场景。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

393

2025.12.29

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

480

2023.08.10

Java 并发编程高级实践
Java 并发编程高级实践

本专题深入讲解 Java 在高并发开发中的核心技术,涵盖线程模型、Thread 与 Runnable、Lock 与 synchronized、原子类、并发容器、线程池(Executor 框架)、阻塞队列、并发工具类(CountDownLatch、Semaphore)、以及高并发系统设计中的关键策略。通过实战案例帮助学习者全面掌握构建高性能并发应用的工程能力。

60

2025.12.01

windows查看端口占用情况
windows查看端口占用情况

Windows端口可以认为是计算机与外界通讯交流的出入口。逻辑意义上的端口一般是指TCP/IP协议中的端口,端口号的范围从0到65535,比如用于浏览网页服务的80端口,用于FTP服务的21端口等等。怎么查看windows端口占用情况呢?php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

576

2023.07.26

查看端口占用情况windows
查看端口占用情况windows

端口占用是指与端口关联的软件占用端口而使得其他应用程序无法使用这些端口,端口占用问题是计算机系统编程领域的一个常见问题,端口占用的根本原因可能是操作系统的一些错误,服务器也可能会出现端口占用问题。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

1097

2023.07.27

windows照片无法显示
windows照片无法显示

当我们尝试打开一张图片时,可能会出现一个错误提示,提示说"Windows照片查看器无法显示此图片,因为计算机上的可用内存不足",本专题为大家提供windows照片无法显示相关的文章,帮助大家解决该问题。

790

2023.08.01

Java 桌面应用开发(JavaFX 实战)
Java 桌面应用开发(JavaFX 实战)

本专题系统讲解 Java 在桌面应用开发领域的实战应用,重点围绕 JavaFX 框架,涵盖界面布局、控件使用、事件处理、FXML、样式美化(CSS)、多线程与UI响应优化,以及桌面应用的打包与发布。通过完整示例项目,帮助学习者掌握 使用 Java 构建现代化、跨平台桌面应用程序的核心能力。

10

2026.01.14

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PostgreSQL 教程
PostgreSQL 教程

共48课时 | 7.1万人学习

Git 教程
Git 教程

共21课时 | 2.7万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号