std::unique_lock为锁管理模板类,是对通用mutex的封装。std::unique_lock对象以独占所有权的方式(unique owership)管理mutex对象的上锁和解锁操作,即在unique_lock对象的声明周期内,它所管理的锁对象会一直保持上锁状态;而unique_lock的生命周期结束之后,它所管理的锁对象会被解锁。unique_lock具有lock_guard的所有功能,而且更为灵活。虽然二者的对象都不能复制,但是unique_lock可以移动(movable),因此用unique_lock管理互斥对象,可以作为函数的返回值,也可以放到STL的容器中。

关于std::mutex的基础介绍可以参考:http://blog.csdn.net/fengbingchun/article/details/73521630

std::unique_lock还支持同时锁定多个mutex,这避免了多道加锁时的资源”死锁”问题。在使用std::condition_variable时需要使用std::unique_lock而不应该使用std::lock_guard。

std::unique_lock类成员函数介绍:

(1). unique_lock构造函数:禁止拷贝构造,允许移动构造;

(2). operator =:赋值操作符,允许移动赋值,禁止拷贝赋值;

(3). operator bool:返回当前std::unique_lock对象是否获得了锁;

(4). lock函数:调用所管理的mutex对象的lock函数;

(5). try_lock函数:调用所管理的mutex对象的try_lock函数;

(6).try_lock_for函数:调用所管理的mutex对象的try_lock_for函数;

(7).try_lock_until函数:调用所管理的mutex对象的try_lock_until函数;

(8). unlock函数:调用所管理的mutex对象的unlock函数;

(9). release函数:返回所管理的mutex对象的指针,并释放所有权,但不改变mutex对象的状态;

(10). owns_lock函数:返回当前std::unique_lock对象是否获得了锁;

(11). mutex函数:返回当前std::unique_lock对象所管理的mutex对象的指针;

(12). swap函数:交换两个unique_lock对象。

The difference is that you can lock and unlock a std::unique_lock. std::lock_guard will be locked only once on construction and unlocked on destruction.

std::unique_lock has other features that allow it to e.g.: be constructed without locking the mutex immediately but to build the RAII wrapper. However, std::unique_lock might have a tad more overhead(较多开销).

std::lock_guard also provides a convenient RAII wrapper, but cannot lock multiple mutexes safely. It can be used when you need a wrapper for a limited scope, e.g.: a member function.

One of the differences between std::lock_guard and std::unique_lock is that the programmer is able to unlock std::unique_lock, but she/he is not able to unlock std::lock_guard.

下面是从其他文章中copy的测试代码,详细内容介绍可以参考对应的reference:

#include "unique_lock.hpp"
#include <iostream>
#include <thread>
#include <mutex>
#include <vector>
#include <chrono>namespace unique_lock_ {//
// reference: http://www.cplusplus.com/reference/mutex/unique_lock/unique_lock/
namespace {
std::mutex foo, bar;void task_a()
{std::lock(foo, bar);         // simultaneous lock (prevents deadlock)std::unique_lock<std::mutex> lck1(foo, std::adopt_lock);std::unique_lock<std::mutex> lck2(bar, std::adopt_lock);std::cout << "task a\n";// (unlocked automatically on destruction of lck1 and lck2)
}void task_b()
{// unique_lock::unique_lock: Constructs a unique_lock// foo.lock(); bar.lock(); // replaced by:std::unique_lock<std::mutex> lck1, lck2;lck1 = std::unique_lock<std::mutex>(bar, std::defer_lock);lck2 = std::unique_lock<std::mutex>(foo, std::defer_lock);std::lock(lck1, lck2);       // simultaneous lock (prevents deadlock)std::cout << "task b\n";// (unlocked automatically on destruction of lck1 and lck2)
}
}int test_unique_lock_1()
{std::thread th1(task_a);std::thread th2(task_b);th1.join();th2.join();return 0;
}/
// reference: http://www.cplusplus.com/reference/mutex/unique_lock/lock/
namespace {
std::mutex mtx;           // mutex for critical sectionvoid print_thread_id(int id) {std::unique_lock<std::mutex> lck(mtx, std::defer_lock);// critical section (exclusive access to std::cout signaled by locking lck):// unique_lock::lock: Calls member lock of the managed mutex object.lck.lock();std::cout << "thread #" << id << '\n';// unique_lock::unlock: Calls member unlock of the managed mutex object, and sets the owning state to falselck.unlock();
}
}int test_unique_lock_2()
{std::thread threads[10];// spawn 10 threads:for (int i = 0; i<10; ++i)threads[i] = std::thread(print_thread_id, i + 1);for (auto& th : threads) th.join();return 0;
}//
// reference: http://www.cplusplus.com/reference/mutex/unique_lock/mutex/
namespace {
class MyMutex : public std::mutex {int _id;
public:MyMutex(int id) : _id(id) {}int id() { return _id; }
};MyMutex mtx3(101);void print_ids(int id) {std::unique_lock<MyMutex> lck(mtx3);// unique_lock::mutex: Returns a pointer to the managed mutex objectstd::cout << "thread #" << id << " locked mutex " << lck.mutex()->id() << '\n';
}
}int test_unique_lock_3()
{std::thread threads[10];// spawn 10 threads:for (int i = 0; i<10; ++i)threads[i] = std::thread(print_ids, i + 1);for (auto& th : threads) th.join();return 0;
}//
// reference: http://www.cplusplus.com/reference/mutex/unique_lock/operator=/
namespace {
std::mutex mtx4;           // mutex for critical sectionvoid print_fifty(char c) {std::unique_lock<std::mutex> lck;         // default-constructed// unique_lock::operator=: Replaces the managed mutex object by the one in x, including its owning statelck = std::unique_lock<std::mutex>(mtx4);  // move-assignedfor (int i = 0; i<50; ++i) { std::cout << c; }std::cout << '\n';
}
}int test_unique_lock_4()
{std::thread th1(print_fifty, '*');std::thread th2(print_fifty, '$');th1.join();th2.join();return 0;
}///
// reference: http://www.cplusplus.com/reference/mutex/unique_lock/operator_bool/
namespace {
std::mutex mtx5;           // mutex for critical sectionvoid print_star() {std::unique_lock<std::mutex> lck(mtx5, std::try_to_lock);// print '*' if successfully locked, 'x' otherwise:// unique_lock::operator bool: Return whether it owns a lockif (lck)std::cout << '*';elsestd::cout << 'x';
}
}int test_unique_lock_5()
{std::vector<std::thread> threads;for (int i = 0; i<500; ++i)threads.emplace_back(print_star);for (auto& x : threads) x.join();return 0;
}///
// reference: http://www.cplusplus.com/reference/mutex/unique_lock/owns_lock/
namespace {
std::mutex mtx6;           // mutex for critical sectionvoid print_star6() {std::unique_lock<std::mutex> lck(mtx6, std::try_to_lock);// print '*' if successfully locked, 'x' otherwise:// unique_lock::owns_lock: Returns whether the object owns a lock.if (lck.owns_lock())std::cout << '*';elsestd::cout << 'x';
}
}int test_unique_lock_6()
{std::vector<std::thread> threads;for (int i = 0; i<500; ++i)threads.emplace_back(print_star6);for (auto& x : threads) x.join();return 0;
}//
// reference: http://www.cplusplus.com/reference/mutex/unique_lock/release/
namespace {
std::mutex mtx7;
int count = 0;void print_count_and_unlock(std::mutex* p_mtx) {std::cout << "count: " << count << '\n';p_mtx->unlock();
}void task() {std::unique_lock<std::mutex> lck(mtx7);++count;// unique_lock::release: Returns a pointer to the managed mutex object, releasing ownership over itprint_count_and_unlock(lck.release());
}
}int test_unique_lock_7()
{std::vector<std::thread> threads;for (int i = 0; i<10; ++i)threads.emplace_back(task);for (auto& x : threads) x.join();return 0;
}/
// reference: http://www.cplusplus.com/reference/mutex/unique_lock/try_lock/
namespace {
std::mutex mtx8;           // mutex for critical sectionvoid print_star8() {std::unique_lock<std::mutex> lck(mtx8, std::defer_lock);// print '*' if successfully locked, 'x' otherwise:// unique_lock::try_lock: Lock mutex if not locked// true if the function succeeds in locking the managed mutex object, false otherwise.if (lck.try_lock())std::cout << '*';elsestd::cout << 'x';
}
}int test_unique_lock_8()
{std::vector<std::thread> threads;for (int i = 0; i<500; ++i)threads.emplace_back(print_star8);for (auto& x : threads) x.join();return 0;
}/
// reference: http://www.cplusplus.com/reference/mutex/unique_lock/try_lock_for/
namespace {
std::timed_mutex mtx9;void fireworks() {std::unique_lock<std::timed_mutex> lck(mtx9, std::defer_lock);// waiting to get a lock: each thread prints "-" every 200ms:// unique_lock::try_lock_for: Try to lock mutex during time spanwhile (!lck.try_lock_for(std::chrono::milliseconds(200))) {std::cout << "-";}// got a lock! - wait for 1s, then this thread prints "*"std::this_thread::sleep_for(std::chrono::milliseconds(1000));std::cout << "*\n";
}
}int test_unique_lock_9()
{std::thread threads[10];// spawn 10 threads:for (int i = 0; i<10; ++i)threads[i] = std::thread(fireworks);for (auto& th : threads) th.join();return 0;
}/
// reference: http://en.cppreference.com/w/cpp/thread/unique_lock
namespace {
struct Box {explicit Box(int num) : num_things{ num } {}int num_things;std::mutex m;
};void transfer(Box& from, Box& to, int num)
{// don't actually take the locks yetstd::unique_lock<std::mutex> lock1(from.m, std::defer_lock);std::unique_lock<std::mutex> lock2(to.m, std::defer_lock);// lock both unique_locks without deadlockstd::lock(lock1, lock2);from.num_things -= num;to.num_things += num;// 'from.m' and 'to.m' mutexes unlocked in 'unique_lock' dtors
}
}int test_unique_lock_10()
{Box acc1(100);Box acc2(50);std::thread t1(transfer, std::ref(acc1), std::ref(acc2), 10);std::thread t2(transfer, std::ref(acc2), std::ref(acc1), 5);t1.join();t2.join();return 0;
}} // namespace unique_lock_

GitHub: https://github.com/fengbingchun/Messy_Test

C++11中std::unique_lock的使用相关推荐

  1. Multi-thread--C++11中std::unique_lock的使用

    std::unique_lock为锁管理模板类,是对通用mutex的封装.std::unique_lock对象以独占所有权的方式(unique owership)管理mutex对象的上锁和解锁操作,即 ...

  2. C++/C++11中std::string用法汇总

    C++/C++11中std::string是个模板类,它是一个标准库.使用string类型必须首先包含<string>头文件.作为标准库的一部分,string定义在命名空间std中. st ...

  3. C++11中std::lock_guard的使用

    互斥类的最重要成员函数是lock()和unlock().在进入临界区时,执行lock()加锁操作,如果这时已经被其它线程锁住,则当前线程在此排队等待.退出临界区时,执行unlock()解锁操作.更好的 ...

  4. C++11中std::condition_variable的使用

    <condition_variable>是C++标准程序库中的一个头文件,定义了C++11标准中的一些用于并发编程时表示条件变量的类与方法等. 条件变量是并发程序设计中的一种控制结构.多个 ...

  5. Multi-thread--C++11中std::lock_guard的使用

    互斥类的最重要成员函数是lock()和unlock().在进入临界区时,执行lock()加锁操作,如果这时已经被其它线程锁住,则当前线程在此排队等待.退出临界区时,执行unlock()解锁操作.更好的 ...

  6. Multi-thread--C++11中std::condition_variable的使用

    <condition_variable>是C++标准程序库中的一个头文件,定义了C++11标准中的一些用于并发编程时表示条件变量的类与方法等. 条件变量是并发程序设计中的一种控制结构.多个 ...

  7. C++11中std::async的使用

    C++11中的std::async是个模板函数.std::async异步调用函数,在某个时候以Args作为参数(可变长参数)调用Fn,无需等待Fn执行完成就可返回,返回结果是个std::future对 ...

  8. C++11中std::packaged_task的使用

    C++11中的std::packaged_task是个模板类.std::packaged_task包装任何可调用目标(函数.lambda表达式.bind表达式.函数对象)以便它可以被异步调用.它的返回 ...

  9. C++11中std::shared_future的使用

    C++11中的std::shared_future是个模板类.与std::future类似,std::shared_future提供了一种访问异步操作结果的机制:不同于std::future,std: ...

最新文章

  1. RHEL7系统管理之内核管理
  2. Spark UDF用户自定义函数
  3. zipkin使用_Sleuth和Zipkin进行分布式链路跟踪,一点课堂(多岸学院)
  4. Cygwin中如何像在Ubuntu中一样安装软件
  5. java queue 实现类 区别_Java集合11 (Queue)
  6. 2349 Arctic Network prim最小生成树 基础
  7. 计算机应用程序错误怎么办 6,WinXP电脑应用程序错误怎么办?
  8. Nacos 日志文件堆满磁盘空间处理方案
  9. JavaScript 之 调用outlook发邮件功能mailto(附带换行问题)
  10. 推荐一款MD5解密在线网站
  11. 霍兰德人格分析雷达图——python实现
  12. zookeeper 删除节点时报错java.io.IOException: Packet len4272892 is out of range!
  13. Pytorch学习之神经网络参数管理
  14. idm下载器去哪里下载 idm下载器用不了什么原因
  15. UESTC 1638 红藕香残玉簟秋,轻解罗裳,独上兰舟。
  16. 默哀STAND SILENTLY!
  17. 世界顶级黑客Kevin D.Mitnick教你如何在数字世界中真正隐形?
  18. python读取数据画三维图_Python实现读取txt文件并画三维图
  19. 【win8优化大师:怎么调整被挤走的图标】
  20. mysql中or详细使用方式(Mysql之and和or混合使用) MES

热门文章

  1. Python Qt GUI设计:将UI文件转换为Python文件的三种妙招(基础篇—2)
  2. Python解析照片EXIF信息,获取坐标位置
  3. 学习《Linux设备模型浅析之驱动篇》笔记(一)
  4. FPGA(5)数码管静态显示与动态显示
  5. 【神经网络】(6) 卷积神经网络(VGG16),案例:鸟类图片4分类
  6. 深度学习——训练时碰到的超参数
  7. keras提取模型中的某一层_keras获得某一层或者某层权重的输出实例
  8. Unity完全学习教程-从初学者到C#中的RPG游戏开发
  9. [BZOJ3779]重组病毒(LCT+DFS序线段树)
  10. NOIP2018TG 初赛复习