解决的问题描述
mutex的实际使用中,在多分支的场景中很容易漏掉解锁,或者需要在方法结束,解锁前将被保护的内容拷贝出来作为返回值,如下例:
bool print_test (int branch)
{
mtx.lock();
if(branch ==1)
{
std::cout << 'branch 1\n';
mtx.unlock();
return false;
}
else if(branch == 2)
{
std::cout << 'branch 2\n';
return false;
}
std::cout << 'conmpleted\n';
mtx.unlock();
return (branch == 0);
}
本例中,假设branch是需要被保护的对象,上例中有两个问题:
第一个问题就是在第二个分支结束的时候,没有解锁,会导致后面的死锁。
第二个问题是在return 处已经解锁后再次访问了branch。
实现代码
实现一个简单的自动管理锁的工具类可以解决上述的问题。
#include <mutex>
class AutoMutex
{
AutoMutex(std::mutex *mtx) :pmtx(mtx)
{
if(pmtx != nullptr)
pmtx->lock();
}
AutoMutex(std::mutex &mtx) :pmtx(&mtx)
{
pmtx->lock();
}
~AutoMutex()
{
if(pmtx != nullptr)
pmtx->unlock();
}
private:
std::mutex *pmtx;
}
使用示例
使用时,只要在方法第一行,实例化工具类,构造传入锁即可。
#include <mutex>
#include <iostream>
static std::mutex mtx;
bool print_test (int branch)
{
AutoMutex automutex(mtx);
if(branch ==1)
{
std::cout << 'branch 1\n';
return false;
}
else if(branch == 2)
{
std::cout << 'branch 2\n';
return false;
}
std::cout << 'conmpleted\n';
return (branch==0);
}
int main ()
{
print_test (1);
print_test (2);
print_test (0);
return 0;
}