这个代码并不难,但看起来很丑,如果你一个函数有 10 个退出点,你就必须为每个退出点调用一次 unlock 方法,或许你可能在某个地方忘掉了 unlock ,那么各种悲剧即将发生,悲剧发生将直接导致程序死锁。
接下来我们看如何解决这个问题。
自动锁管理
当你需要包含整段的代码(在我们这里是一个方法,也可能是一个循环体或者其他的控制结构),有这么一种好的解决方法可以避免忘记释放锁,那就是 std::lock_guard.
这个类是一个简单的智能锁管理器,但创建 std::lock_guard 时,会自动调用互斥量对象的 lock() 方法,当 lock_guard 析构时会自动释放锁,请看下面代码:
- struct ConcurrentSafeCounter { std::mutex mutex;
- Counter counter;
- void increment(){ std::lock_guard<std::mutex> guard(mutex);
- counter.increment(); }
- void decrement(){
- std::lock_guard<std::mutex> guar(mutex); mutex.unlock();
- } };
是不是看起来爽多了?
使用 lock_guard ,你不再需要考虑什么时候要释放锁,这个工作已经由 std::lock_guard 实例帮你完成。
结论
在这篇文章中我们学习了如何通过信号量/互斥量来保护共享数据。需要记住的是,使用锁会降低程序性能。在一些高并发的应用环境中有其他更好的解决办法,不过这不在本文的讨论范畴之内。
你可以在 Github 上获取本文的源码.










