跳转到内容

C++/shared mutex

维基教科书,自由的教学读本
< C++

头文件 <shared_mutex>是C++14提出的STL的通用的共享互斥所有权的包装器。以共享模式锁定关联的shared_lock;而std::unique_lock 可用于以排他性模式锁定。

shared_lock 类可移动,但不可复制——它满足可移动构造 (MoveConstructible) 与可移动赋值 (MoveAssignable) 的要求,但不满足可复制构造 (CopyConstructible) 或可复制赋值 (CopyAssignable) 。

shared_mutex 类

[编辑]

shared_mutex类是一个同步原语,用于实现读写互斥锁。shared_mutex 拥有二个访问级别:

  • 共享 - 多个线程能共享同一互斥的所有权。 线程通过lock 、 try_lock等成员函数获取独占性锁。
  • 独占性 - 仅一个线程能占有互斥。 通过 lock_shared 、 try_lock_shared等成员函数获取共享锁。

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

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

成员类型

[编辑]

native_handle_type(可选) 实现定义

成员函数

[编辑]
  • (构造函数)
  • (析构函数)
  • operator=[被删除] 不可复制赋值
  • lock 锁定互斥,若互斥不可用则阻塞
  • try_lock 尝试锁定互斥,若互斥不可用则返回
  • unlock 解锁互斥
  • lock_shared 为共享所有权锁定互斥,若互斥不可用则阻塞
  • try_lock_shared 尝试为共享所有权锁定互斥,若互斥不可用则返回
  • unlock_shared 解锁互斥(共享所有权)
  • native_handle 返回底层实现定义的原生句柄

shared_timed_mutex 类

[编辑]

shared_timed_mutex类实现了带时限的读写锁。

shared_timed_mutex 类满足共享定时互斥体 (SharedTimedMutex) 和标准布局类型 (StandardLayoutType) 的所有要求。

成员函数

[编辑]
  • (构造函数)
  • (析构函数)
  • operator=[被删除] 不可复制赋值
  • lock 锁定互斥,若互斥不可用则阻塞
  • try_lock 尝试锁定互斥,若互斥不可用则返回
  • try_lock_for 尝试锁定互斥,若互斥在指定的时限时期中不可用则返回
  • try_lock_until 尝试锁定互斥,若直至抵达指定时间点互斥不可用则返回
  • unlock 解锁互斥
  • lock_shared 为共享所有权锁定互斥,若互斥不可用则阻塞
  • try_lock_shared 尝试为共享所有权锁定互斥,若互斥不可用则返回
  • try_lock_shared_for 尝试为共享所有权锁定互斥,若互斥在指定的时限时期中不可用则返回
  • try_lock_shared_until 尝试为共享所有权锁定互斥,若直至抵达指定时间点互斥不可用则返回
  • unlock_shared 解锁互斥(共享所有权)

std::shared_lock类模板

[编辑]

模板形参

[编辑]
  • Mutex 要锁定的共享互斥的类型。

成员类型

[编辑]
  • mutex_type 定义为Mutex

成员函数

[编辑]
  • (构造函数)
  • (析构函数) 解锁关联的互斥
  • operator= 若占有则解锁互斥,然后获得对方的所有权
  • lock 锁定关联的互斥
  • try_lock 尝试锁定关联的互斥
  • try_lock_for 尝试锁定关联的互斥,以指定时长
  • try_lock_until 尝试锁定关联的互斥,直至指定的时间点
  • unlock 解锁关联的互斥
  • swap 与另一 shared_lock 交换数据成员
  • release 解除关联 mutex 而不解锁
  • mutex 返回指向关联的互斥的指针
  • owns_lock 测试锁是否占有其关联的互斥
  • operator bool 测试锁是否占有其关联的互斥

例子

[编辑]
#include <iostream>
#include <mutex>  // 对于 std::unique_lock
#include <shared_mutex>
#include <thread>
 
class ThreadSafeCounter {
 public:
  ThreadSafeCounter() = default;
 
  // 多个线程/读者能同时读计数器的值。
  unsigned int get() const {
    std::shared_lock<std::shared_mutex> lock(mutex_);
    return value_;
  }
 
  // 只有一个线程/写者能增加/写线程的值。
  void increment() {
    std::unique_lock<std::shared_mutex> lock(mutex_);
    value_++;
  }
 
  // 只有一个线程/写者能重置/写线程的值。
  void reset() {
    std::unique_lock<std::shared_mutex> lock(mutex_);
    value_ = 0;
  }
 
 private:
  mutable std::shared_mutex mutex_;
  unsigned int value_ = 0;
};
 
int main() {
  ThreadSafeCounter counter;
 
  auto increment_and_print = [&counter]() {
    for (int i = 0; i < 3; i++) {
      counter.increment();
      std::cout << std::this_thread::get_id() << ' ' << counter.get() << '\n';
 
      // 注意:写入 std::cout 实际上也要由另一互斥同步。省略它以保持示例简洁。
    }
  };
 
  std::thread thread1(increment_and_print);
  std::thread thread2(increment_and_print);
 
  thread1.join();
  thread2.join();
}