引言
在学习C++多线程编程的时候我们总会看到人们把lock_guard与unique_lock去做比较 并说unique_lock更加灵活 这篇文章就简单的说下为什么unique_lock更加灵活
我们首先来看下两个类分别支持的函数
这是unique_lock的
这是lock_guard
我们可以看到其实相比于unique_lock, lock_guard可以说不支持什么函数,其实lock_guard的存在就是一个RAII的体现,其不支持任何函数,也就是说对象创建时上锁,对象存在期间拥有锁,对象消亡时解锁,这样当然有好处,就是友好的资源管理,但是其限定了锁的语义,就是说,对象存在期间必须拥有锁(有例外),且在消亡前不能释放锁,友好的资源管理和资源消耗带来的是笨重的功能,所以我们可以说,不是unique_lock太灵活 而是lock_guard太不灵活了.
ps:上面所说的例外就是在构造lock_guard时可以传入参数std::adopt_lock,这样可以使lock_guard存在时不占有锁,但是还是会解锁
功能上的差别意味着灵活性,我们从所支持的函数上来看,unique_lock其实和一个锁所支持的功能相差无几(CAS除外),这也意味着其在资源管理时能做的更多,举个简单的例子,比如条件变量的wait操作,我们都知道这个函数涉及到lock与unlock,在这种情况下我们只能使用unique_lock,所以在wait的参数中,标准库只能支持unique_lock
上面提到了std::adopt_lock,unique_lock当然也支持,而且因为unique_lock本身支持lock操作,其还支持一个参数std::defer_lock,可以让构造函数中不进行上锁,这同样也是灵活性的一个体现
还有一点不得不提,C++的编译器多态意味着unique_lock甚至可以作为参数传给std::lock,只需要让unique_lock在构造时不要上锁,我们使用std::defer_lock就可以解决
效率问题
我们可能一直会说unique_lock会有些许的消耗,这是当然,但是确实是些许 我们来看看两个对象内部的数据
很明显 下面的那个是unique_lock 其实只是用一个bool值来标记当前是否上锁 防止在lock时再lock 造成死锁,但是虽然是些许,也终究是有的,所以我们的原则就是能用lock_guard就用,否则使用unique_lock