跨平台实现std::shared_mutex的轻量级C++方案

在C++17及之后的标准中,std::shared_mutex 为多线程程序提供了读写锁的功能,允许多个线程同时读取共享资源,而写线程则拥有独占访问权。然而,标准库的实现往往依赖于底层操作系统的同步原语(如 pthread_rwlock_t 或 Windows 的 SRWLOCK),这会导致跨平台项目在不同编译器或平台上出现兼容性问题。本文将从零开始实现一个轻量级、跨平台的 shared_mutex,并演示其使用场景。

1. 设计目标

  1. 跨平台:在 POSIX 系统(Linux、macOS)以及 Windows 上均能编译并运行。
  2. 性能优先:对读操作采用无锁或轻量级锁,避免不必要的上下文切换。
  3. 易于使用:遵循 std::shared_lock / std::unique_lock 接口的使用方式。
  4. 可扩展:支持升级为写锁、降级为读锁等高级操作。

2. 关键技术点

2.1 读写计数器与互斥锁

使用一个原子整数 `std::atomic

` 表示: – 正在读的线程数(高位)。 – 写锁持有状态(低位)。 “`cpp struct SharedMutexState { std::atomic counter; // 0: free, >0: readers, -1: writer }; “` #### 2.2 读锁的实现 读锁需要: 1. 读取计数器。 2. 若无写锁持有(`counter >= 0`),递增计数器。 3. 若写锁持有(`counter = 0 && !counter.compare_exchange_weak( expected, expected + 1, std::memory_order_acquire, std::memory_order_relaxed)) { // 如果 counter 变为负值,则写锁已存在,读锁失败 if (expected #include #include #include class SimpleSharedMutex { public: SimpleSharedMutex() : state_(0) {} // 禁止拷贝和移动 SimpleSharedMutex(const SimpleSharedMutex&) = delete; SimpleSharedMutex& operator=(const SimpleSharedMutex&) = delete; // 读锁 void lock_shared() { std::unique_lock lk(m_); while (!try_lock_shared()) { cv_.wait(lk); } } // 写锁 void lock() { std::unique_lock lk(m_); while (!try_lock()) { cv_.wait(lk); } } void unlock_shared() { if (!try_unlock_shared()) { throw std::runtime_error(“unlock_shared failed”); } } void unlock() { if (!try_unlock()) { throw std::runtime_error(“unlock failed”); } } // 仅尝试性尝试获取 bool try_lock_shared() { int cur = state_.load(std::memory_order_relaxed); while (cur >= 0) { if (state_.compare_exchange_weak( cur, cur + 1, std::memory_order_acquire, std::memory_order_relaxed)) return true; } return false; } bool try_lock() { int zero = 0; return state_.compare_exchange_strong( zero, -1, std::memory_order_acquire, std::memory_order_relaxed); } private: bool try_unlock_shared() { int cur = state_.load(std::memory_order_relaxed); if (cur state_; std::mutex m_; std::condition_variable cv_; }; “` ### 4. 使用示例 “`cpp #include #include #include “SimpleSharedMutex.hpp” SimpleSharedMutex g_mutex; int shared_data = 0; void reader(int id) { for (int i = 0; i

发表评论