void lock(Mutex* pm); // 锁定pm所指的互斥器 void unlock(Mutex* pm); // 将互斥器解除锁定为确保绝不会忘记将一个被锁住的Mutex解锁,可能会希望建立一个 class 来管理解锁.这样的 class 的基本结构由RAII守则支配,也就是"资源在构造期间获得,在析构期间释放":
class Lock {
public:
explicit Lock(Mutex* pm) : mutexPtr(pm) {
lock(mutexPtr); // 获得资源
}
~Lock() {
unlock(mutexPtr); // 释放资源
}
private:
Mutex* mutexPtr;
}; 客户对Lock的用法符合RAII方式: Mutex m; // 定义需要的互斥器
...
{ // 建立一个区块用来定义critical section
Lock m1(&m); // 锁定互斥器
... // 执行critical section内的操作
} // 在区块最末尾,自动解除互斥器锁定 这很好,但如果Lock对象被赋值,会发生什么事? Lock ml1(&m); // 锁定m Lock ml2(ml1); // 将ml1复制到ml2上,这会发生什么事?这是某个一般化问题的特定例子."当一个RAII对象被复制,会发生什么事情?",大多数时候会选择以下两种可能:
class Lock : private Uncopyable { // 禁止复制,详见条款6
public:
...
};
2.对底层资源祭出"引用计数法"(reference-count).有时候希望保有资源,直到它的最后一个使用者被销毁.这种情况下复制RAII对象时,应该将资源的"被引用数"递增.tr1::shared_ptr便是如此.
class Lock {
public:
explicit Lock(Mutex* pm) // 以某个Mutex初始化shared_ptr
: mutexPtr(pm, unlock) // 并以unlock函数为删除器
{
lock(mutexPtr.get()); // 条款15谈到"get"
}
private: // 使用shared_ptr替换raw pointer
std::tr1::shared_ptr<Mutex> mutexPtr;
};
本例中的Lock class 不再声明析构函数,因为没有必要.条款5说过,class 析构函数(不论是编译器生成的,或用户自定义的)会自动调用其non-static 成员变量(本例为mutexPtr)的析构函数.而mutexptr的析构函数会在互斥器的引用次数为0时自动调用tr1::shared_ptr的删除器(本例为unlock).
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文:http://blog.csdn.net/yiranant/article/details/48143563