您的位置:首页 > 编程语言 > C语言/C++

C++11之lock_guard学习总结和代码实例

2016-07-27 22:47 417 查看
std::lock_gurad 是 C++11 中定义的模板类。定义如下:

template<class _Mutex>
class lock_guard
{   // class with destructor that unlocks mutex
public:
typedef _Mutex mutex_type;

explicit lock_guard(_Mutex& _Mtx)
: _MyMutex(_Mtx)
{   // construct and lock
_MyMutex.lock();
}

lock_guard(_Mutex& _Mtx, adopt_lock_t)
: _MyMutex(_Mtx)
{   // construct but don't lock
}

~lock_guard() _NOEXCEPT
{   // unlock
_MyMutex.unlock();
}

lock_guard(const lock_guard&) = delete;
lock_guard& operator=(const lock_guard&) = delete;

private:
_Mutex& _MyMutex;
};


在 lock_guard 对象构造时,传入的 Mutex 对象(即它所管理的 Mutex 对象)会被当前线程锁住。在lock_guard 对象被析构时,它所管理的 Mutex 对象会自动解锁,由于不需要程序员手动调用 lock 和 unlock 对 Mutex 进行上锁和解锁操作,因此这也是最简单安全的上锁和解锁方式,尤其是在程序抛出异常后先前已被上锁的 Mutex 对象可以正确进行解锁操作,极大地简化了程序员编写与 Mutex 相关的异常处理代码。

代码中

lock_guard(const lock_guard&) = delete;

lock_guard& operator=(const lock_guard&) = delete;

禁用了拷贝构造函数和赋值构造函数.保证了 lock_guard 对象的所有权不会被转移.

代码参考地址,这哥们讲解的很透彻,

http://blog.csdn.net/liuxuejiang158blog/article/details/17241387

代码实例1:使用固定顺序获取锁

#include <mutex>
#include<unistd.h>
#include<thread>
#include<iostream>
using namespace std;
class big_object
{
public:
big_object(int i=0):data(i){}
public:
int data;
};

void swap(big_object& lhs,big_object& rhs)
{
sleep(1);
cout<<"swap()"<<endl;
}
class X
{
private:
big_object some_detail;
mutable std::mutex m;
public:
X(big_object const& sd):some_detail(sd){}

friend void swap(X& lhs, X& rhs)
{
if(&lhs==&rhs)
return;
std::lock(lhs.m,rhs.m);//C++库会自动生成加锁顺序,即使调用顺序不一致
std::lock_guard<std::mutex> lock_a(lhs.m,std::adopt_lock);//adopt_lock是告诉lock_guard对象mutex已经被上锁,而lock_gurad对象将获得mutex的所有权,这样就可以保证在lock可能出现异常导致没有unlock的情形不会出现,栈对象会在异常抛出后自动析构
std::lock_guard<std::mutex> lock_b(rhs.m,std::adopt_lock);
swap(lhs.some_detail,rhs.some_detail);
}
};
void threadFun(X& one,X& two){
swap(one,two);
}
int main()
{
big_object ten(10),hundred(100);
X one(ten),two(hundred);
thread threadOne(threadFun,ref(one),ref(two));//不同线程有不同的参数调用顺序,ref表示传递的是引用,否则只有线程函数中传引用无效
thread threadTwo(threadFun,ref(two),ref(one));
threadOne.join();
threadTwo.join();
return 0;
}


代码实例2:层次锁

lock hierarchy指的是给每个mutex分配一个标号从而对mutex逻辑排序。限制条件是:当线程已经持有编号比n小的锁时不能再请求标号为n的mutex.

#include <mutex>
#include <stdexcept>
class hierarchical_mutex//可用于lock_guard<hierarchical_mutex>
{
std::mutex internal_mutex;//
unsigned long const hierarchy_value;//mutex所在的层次
unsigned long previous_hierarchy_value;//记录前一个mutex的层次,用于解锁时恢复线程的层次
static thread_local unsigned long this_thread_hierarchy_value;//线程所在的层次,是个线程私有数据

void check_for_hierarchy_violation()//检查当前mutex是否小于线程层次,不是则抛出异常
{
if(this_thread_hierarchy_value <= hierarchy_value)
{
throw std::logic_error("mutex hierarchy violated");
}
}
void update_hierarchy_value()//更新线程的层次
{
previous_hierarchy_value=this_thread_hierarchy_value;//通过previous_hierarchy_value记住线程的层次
this_thread_hierarchy_value=hierarchy_value;//用当前mutex的层次更新线程层次
}
public:
explicit hierarchical_mutex(unsigned long value):
hierarchy_value(value),//mutex层次初始值
previous_hierarchy_value(0)
{}
void lock()//对mutex加锁
{
check_for_hierarchy_violation();//先检查,保证mutex层次小于线程层次
internal_mutex.lock();
update_hierarchy_value();//更新线程层次
}
void unlock()//对mutex解锁
{
this_thread_hierarchy_value=previous_hierarchy_value;//用记录的previous_hierarchy_value恢复线程层次
internal_mutex.unlock();
}
bool try_lock()//尝试加锁,若mutex已被其它上锁则返回false
{
check_for_hierarchy_violation();
if(!internal_mutex.try_lock())
return false;
update_hierarchy_value();
return true;
}
};
thread_local unsigned long
hierarchical_mutex::this_thread_hierarchy_value(ULONG_MAX);//线程层次初始值为最大,保证开始可以对任意mutex上锁
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息