C++11中std unique lock的使用

               

 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 false lck.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 object std::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 state lck = std::unique_lock<std::mutex>(mtx4);  // move-assigned for (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 lock if (lck)  std::cout << '*'else  std::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 << '*'else  std::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 it print_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 << '*'else  std::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 span while (!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_locknamespace {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 yet std::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 deadlock std::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_

  GitHubhttps://github.com/fengbingchun/Messy_Test             

再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值