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