可手动实现最小RAII锁包装器:构造时加锁、析构时解锁,禁用拷贝,用指针存锁对象以避免临时对象绑定;若需延迟加锁,则分离lock()调用,如simple_unique_lock。

为什么不能直接用 std::lock_guard 就自己写?
多数场景下,std::lock_guard 已足够——它在构造时加锁、析构时自动释放,符合 RAII 原则。但自己实现一个简化版,有助于理解底层逻辑:比如控制加锁时机(延迟构造时不立即加锁)、支持可重入判断、或封装自定义锁类型(如读写锁的升级逻辑)。关键不是“替代”,而是“可控”。
如何手动实现一个最小可用的 RAII 锁包装器?
核心是把锁对象指针存为成员,并在析构函数中调用 unlock();构造函数是否加锁,取决于设计意图。常见做法是「构造即加锁」,与 std::lock_guard 一致:
template <typename Mutex>
class simple_lock_guard {
Mutex* mtx_;
bool owns_;
<p>public:
explicit simple_lock<em>guard(Mutex& mtx) : mtx</em>(&mtx), owns<em>(true) {
mtx</em>.lock(); // 构造时阻塞加锁
}</p><pre class='brush:php;toolbar:false;'>~simple_lock_guard() {
if (owns_) mtx_->unlock();
}
simple_lock_guard(const simple_lock_guard&) = delete;
simple_lock_guard& operator=(const simple_lock_guard&) = delete;};
注意点:
立即学习“C++免费学习笔记(深入)”;
-
mtx_存指针而非引用,避免临时对象绑定问题 - 禁用拷贝——RAII 对象不可复制,否则析构时会重复 unlock
- 未实现移动语义,若需转移所有权,得额外加
release()方法并置owns_ = false
构造时不加锁,到需要时再 lock 怎么办?
这是 std::unique_lock 的典型行为,适用于条件变量等待、延迟加锁等场景。手动实现只需分离构造与加锁动作:
template <typename Mutex>
class simple_unique_lock {
Mutex* mtx_;
bool owns_;
<p>public:
simple_unique<em>lock() : mtx</em>(nullptr), owns_(false) {}</p><pre class='brush:php;toolbar:false;'>explicit simple_unique_lock(Mutex& mtx) : mtx_(&mtx), owns_(false) {}
void lock() {
if (!owns_ && mtx_) {
mtx_->lock();
owns_ = true;
}
}
void unlock() {
if (owns_ && mtx_) {
mtx_->unlock();
owns_ = false;
}
}
~simple_unique_lock() {
if (owns_ && mtx_) mtx_->unlock();
}
// 禁用拷贝,允许移动(可选)
simple_unique_lock(const simple_unique_lock&) = delete;
simple_unique_lock& operator=(const simple_unique_lock&) = delete;};
常见误用:
- 忘记检查
owns_就调用unlock()→ 可能对未加锁的 mutex 解锁,UB - 构造传入临时
Mutex对象 →mtx_指向已销毁内存 - 移动后未重置原对象的
owns_和mtx_→ 析构时 double-unlock
析构函数里抛异常会怎样?
如果 unlock() 抛异常(比如锁已被破坏、系统资源失效),而此时栈正在展开(例如另一个异常已发生),程序会直接调用 std::terminate。C++ 标准要求互斥量的 unlock() 是 noexcept 的,所以实际中应确保:
- 所用
Mutex类型的unlock()不抛异常(如std::mutex满足) - 不要在 RAII 析构函数里做任何可能抛异常的操作(日志、网络调用等)
- 若必须处理错误,用
try/catch吞掉异常并记录,但不 re-throw
真正容易被忽略的是:析构函数的异常安全性不是靠“写得漂亮”,而是靠“别让它发生”。RAII 的干净,建立在底层资源操作的确定性之上。











