C++多线程-第二篇-Mutex(互斥量)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/hffhjh111/article/details/53140909

//Boost
#include<boost/thread/thread.hpp>
#define BOOST_THREAD_VERSION 4 //使用最新版本,含有1,2,3但只是为了兼容之前程序。

Thread库丰富强大的扩展功能但不在Thread中的未看。

//C++11

#include <mutex>

using namspace std; 


Mutex(互斥量)

1.Mutex类

基本作用: 互斥占有一个变量,一段时间内仅一个线程可以访问。

即该类可以限制对某物的访问,只有先获得许可才可访问某物,否则一般可设为阻塞等待。

互斥量*6

mull_mutex

无任何锁定功能的“互斥量”,空对象模式是用。

mutex

独占式互斥量,最简单但最常用

timed_mutex

独占式互斥量,一段时间内试图锁定,若超时则返回false

recursive_mutex

递归式互斥量,可以多次锁定,相应的也要多次解锁

Recursive_timed_mutex

递归式互斥量,同样增加一段时间内试图锁定,若超时则返回false

Shared_mutex

多读者,单写者的共享互斥量(读写锁)

一般成员函数:

Class Mutex

{

Public:

Void lock(); //锁定,否则阻塞

Void unlock(); // 解锁

Bool try_lock(); //尝试锁定,但不会阻塞

Bool try_lock_for(const duration &rel_time); //timed_ 特有,阻塞一段时间后尝试锁定

Bool try_lock_until(const time_point &t);// timed_ 特有,阻塞一段时间后尝试锁定

 

others...

};

Code:


  
  
  1. mutex mutex_thread_1;
  2. try
  3. {
  4. mutex_thread_1.lock();
  5. cout << "Do Something" << endl;
  6. mutex_thread_1.unlock();
  7. }
  8. catch ( std::exception e)
  9. {
  10. //cout << << endl;;
  11. mutex_thread_1.unlock();
  12. }
  13. timed_mutex t_mutex_1;
  14. auto flag = t_mutex_1.try_lock_for(boost::chrono::milliseconds( 100));
  15. if (flag)
  16. {
  17. cout << "访问共享" << endl;
  18. t_mutex_1.unlock();
  19. }
  20. else
  21. {
  22. cout << "未获得锁,进行其他操作" << endl;
  23. }

2.Lock_guard()-- Mute的优秀辅助

作用:此类辅助锁定互斥量,构造时锁定,析构时解锁,避免遗忘解锁,也就是说在其作用域内他会一直锁定要求的变量。

类似智能指针?

附加扩展:with_lock_guard()借助lock_guard()在函数中互斥使用某锁定资源,(封装函数用?)


  
  
  1. mutex mu;
  2. lock_guard<mutex> g(mu); //作用域内自动智能加锁/解锁
  3. cout << "Do something" << endl;
  4. timed_mutex t_mu;
  5. if (mu.try_lock_for(boost::chrono::microseconds( 100)))
  6. {
  7. lock_guard<timed_mutex> g(t_mu,adopt_lock); //不会再次加锁
  8. cout << "Do something" << endl;
  9. }

  
  
  1. <code class="language-cpp">#include <boost/thread/with_lock_guard.hpp></code>  
#include <boost/thread/with_lock_guard.hpp>
   
   

  
  
  1. #bind()封装用
  2. //with_lock_guard
  3. mutex fmu;
  4. string name = "ZGJ";
  5. int rul = with_lock_guard(fmu, bind(Alloa,argv1,argv2...)); //添加参数需谨慎,为Boost中参数类型,Alloa为函数,argv为其参数
  6. cout << rul << endl;
  7. With_lock_guard(lockable& m, Function && fun, Args &&...args) 类似于
  8. {
  9. Lock_guard<lockable> g(m);
  10. Return func(argc...)
  11. }


3. unique_lock()--升级lock_guard()

该类有很丰富的选项,但不可复制。例如:锁定选项---占有但不锁定

如构造函数有

 unique_lock(Lockable & mu) ;//锁定

 unique_lock(Lockable & mu,boost::adopt_lock_t);//不锁定,但会解锁

 unique_lock(Lockable & mu,boost::defer_lock_t);//不锁定互斥量

 unique_lock(Lockable & mu,boost::try_to_lock_t);//尝试锁定互斥量

 unique_lock(Lockable & mu,const time_point &t);//超时锁定


make_unique_lock(Lockable &mu,option);

//基于unique_lock(),利用函数重载帮助我们不用输入互斥量类型,其实就是类似于

templat<class T_>

unique_lock<lockable> my_make_unique_lock(lockable& mu, T_ my_x)

{
return unique_lock<lockable>(mux,my_x);

}


Code:


  
  
  1. #include<boost\thread\lock_factories.hpp>
  2. mutex m_un_lock;

  
  
  1. { //此类大括号活用作用域,供 make_unique_lock析构使用。
  2. auto g = make_unique_lock(m_un_lock); //工厂函数锁定互斥量
  3. assert(g.owns_lock()); //断言 -- 已经锁定
  4. cout << "Do something" << endl;
  5. }
  6. {
  7. auto g = make_unique_lock(m_un_lock, defer_lock); //暂不锁定互斥量
  8. assert(!g); // 断言 -- 没有锁定
  9. assert(g.try_lock()); //尝试锁定
  10. assert(g); //断言 -- 已经锁定
  11. cout << "Do something" << endl;
  12. }
  13. timed_mutex t_mu_un;
  14. {
  15. auto g = unique_lock<timed_mutex>(t_mu_un, boost::chrono::milliseconds( 100)); //限时100MS尝试锁定
  16. if (g)
  17. {
  18. cout << "Lock timed mutex" << endl;
  19. }
  20. }
  21. auto g = make_unique_locks(t_mu_un, m_un_lock); //同时锁定多个互斥量
  22. assert( std::tuple_size< decltype(g)>::value == 2); //测试是否锁定2个


4.Lock适配器/Lock概念检查/lock函数

4.1Lock适配器

帮助我们实现自己的线程安全的类。即当我们写的类继承了lock适配器,那么我们的类可以被lock_guard()/unique_lock()锁定。

Lock_guard 与 unique_lock是模板类所以只要是满足<LockAble>(含有lock/unlock/try_lock

的接口的类都可以使用它,实现原子操作等。

Lockable适配器类就是为了方便我们实现Lockable的。

Basic_lockable_adapter 

最简单接口,提供lockunlock

Lockable_adapter

基本接口,增加try_lock

Timed_lockable_adapter

增加try_lock_for/try_lock_until

Code:


  
  
  1. #include<iostream>
  2. #include<boost/thread/thread.hpp>
  3. #include<boost/atomic.hpp>//原子库
  4. #include<boost/thread/lockable_adapter.hpp> //Lockable 适配器
  5. #include<boost/thread/lock_factories.hpp>
  6. using namespace std;
  7. using namespace boost;
  8. class account : public lockable_adapter<mutex>
  9. {
  10. private:
  11. atomic< int> m_money_{ 0 }; //账户金额
  12. public:
  13. account(){}
  14. ~account(){}
  15. int sum()const
  16. {
  17. return m_money_;
  18. }
  19. void withdraw(int x)
  20. {
  21. m_money_ -= x;
  22. }
  23. void deposit(int x)//存钱
  24. {
  25. m_money_ += x;
  26. }
  27. void show()
  28. {
  29. cout << m_money_ << endl;
  30. }
  31. };
  32. int main()
  33. {
  34. account a;
  35. {
  36. auto g = make_unique_lock(a);
  37. a.deposit( 100);
  38. a.show();
  39. a.withdraw( 20);
  40. a.show();
  41. assert(a.sum() == 80);
  42. }
  43. {
  44. auto b = make_unique_lock(a, try_to_lock);
  45. if (b)
  46. {
  47. a.withdraw(a.sum());
  48. assert(a.sum() == 0);
  49. a.show();
  50. }
  51. }
  52. return 0;
  53. }


4.2.Lock概念检查

概念检查类保证我们在泛型编程时确保使用的模板参数满足Lockable该每年,在编译时保证程序的正确性。

4.3.Lock函数

Lock() / try_lock()操作mutex类似make_unique_locks() 可以一起锁定多个Mutex,而且保证不会死锁。他们不具有退出作用域自动解锁,但他们在自身异常时会解除锁定

所以一般配合unique_lockadopt_lock或者defer_lock锁定选项,但暂时不锁定互斥量.

Code:


  
  
  1. mutex m1, m2;
  2. {
  3. auto g1 = make_unique_lock(m1, adopt_lock);
  4. auto g2 = make_unique_lock(m2, adopt_lock);
  5. lock(m1, m2);
  6. } //unique_lock自动解锁
  7. {
  8. auto g1 = make_unique_lock(m1, defer_lock);
  9. auto g2 = make_unique_lock(m2, defer_lock);
  10. try_lock(g1, g2);
  11. } //unique_lock自动解锁

5.补:Shared_mutex.

一个特权--写,多个普权--


Code:


  
  
  1. #include<iostream>
  2. #include<boost/thread/thread.hpp>
  3. #include<boost/chrono.hpp>
  4. #include<boost/bind.hpp>
  5. #include<boost/ref.hpp>
  6. using namespace std;
  7. using namespace boost;
  8. class rw_data
  9. {
  10. private:
  11. int m_x;
  12. shared_mutex rw_mu;
  13. public:
  14. rw_data() :m_x( 0){}
  15. void write()
  16. {
  17. unique_lock<shared_mutex> g(rw_mu);
  18. ++m_x;
  19. }
  20. void read(int &x)
  21. {
  22. shared_lock<shared_mutex> g(rw_mu);
  23. x = m_x;
  24. }
  25. };
  26. mutex xzz;
  27. void writer(rw_data &d)
  28. {
  29. for ( int i = 0; i < 2; ++i)
  30. {
  31. this_thread::sleep_for(chrono::microseconds( 3000));
  32. d.write();
  33. }
  34. }
  35. void reader(rw_data &d)
  36. {
  37. int x;
  38. for ( int i = 0; i < 10; i++)
  39. {
  40. this_thread::sleep_for(chrono::microseconds( 5000));
  41. d.read(x);
  42. xzz.lock();
  43. cout << this_thread::get_id() << "reader:" << x << endl;
  44. xzz.unlock();
  45. }
  46. }
  47. int main()
  48. {
  49. //读写锁机制
  50. rw_data d;
  51. thread_group pool;
  52. pool.create_thread(bind(writer, boost::ref(d)));
  53. pool.create_thread(bind(writer, boost::ref(d)));
  54. pool.create_thread(bind(reader, boost::ref(d)));
  55. pool.create_thread(bind(reader, boost::ref(d)));
  56. pool.create_thread(bind(reader, boost::ref(d)));
  57. pool.create_thread(bind(reader, boost::ref(d)));
  58. pool.join_all();
  59. std::system( "pause");
  60. return 0;
  61. }



版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/hffhjh111/article/details/53140909

猜你喜欢

转载自blog.csdn.net/monk1992/article/details/82868495
今日推荐