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

来源:互联网 发布:棋牌全套源码 编辑:程序博客网 时间:2024/06/15 22:44

//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:

mutex mutex_thread_1;try{mutex_thread_1.lock();cout << "Do Something" << endl;mutex_thread_1.unlock();}catch (std::exception e){//cout <<  << endl;;mutex_thread_1.unlock();}timed_mutex t_mutex_1;auto flag = t_mutex_1.try_lock_for(boost::chrono::milliseconds(100));if (flag){cout << "访问共享" << endl;t_mutex_1.unlock();}else{cout << "未获得锁,进行其他操作" << endl;}

 

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

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

类似智能指针?

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

 

mutex mu;lock_guard<mutex> g(mu);//作用域内自动智能加锁/解锁cout << "Do  something" << endl;timed_mutex t_mu;if (mu.try_lock_for(boost::chrono::microseconds(100))){lock_guard<timed_mutex> g(t_mu,adopt_lock);//不会再次加锁cout << "Do something" << endl;}
#include <boost/thread/with_lock_guard.hpp>
#bind()封装用//with_lock_guardmutex fmu;string name = "ZGJ";int rul = with_lock_guard(fmu, bind(Alloa,argv1,argv2...));//添加参数需谨慎,为Boost中参数类型,Alloa为函数,argv为其参数cout << rul << endl;With_lock_guard(lockable& m, Function && fun, Args &&...args) 类似于{Lock_guard<lockable> g(m);Return func(argc...)}


 

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:

#include<boost\thread\lock_factories.hpp>mutex m_un_lock;
{//此类大括号活用作用域,供make_unique_lock析构使用。auto g = make_unique_lock(m_un_lock);//工厂函数锁定互斥量assert(g.owns_lock());//断言 -- 已经锁定cout << "Do something" << endl;}{auto g = make_unique_lock(m_un_lock, defer_lock);//暂不锁定互斥量assert(!g);// 断言 -- 没有锁定assert(g.try_lock());//尝试锁定assert(g);//断言 -- 已经锁定cout << "Do something" << endl;}timed_mutex t_mu_un;{auto g = unique_lock<timed_mutex>(t_mu_un, boost::chrono::milliseconds(100)); //限时100MS尝试锁定if (g){cout << "Lock timed mutex" << endl;}}auto g = make_unique_locks(t_mu_un, m_un_lock);//同时锁定多个互斥量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:

#include<iostream>#include<boost/thread/thread.hpp>#include<boost/atomic.hpp>//原子库#include<boost/thread/lockable_adapter.hpp> //Lockable 适配器#include<boost/thread/lock_factories.hpp>using namespace std;using namespace boost;class account : public lockable_adapter<mutex>{private:atomic<int> m_money_{ 0 }; //账户金额public:account(){}~account(){}int sum()const{return m_money_;}void withdraw(int x){m_money_ -= x;}void deposit(int x)//存钱{m_money_ += x;}void show(){cout << m_money_ << endl;}};int main(){account a;{auto g = make_unique_lock(a);a.deposit(100);a.show();a.withdraw(20);a.show();assert(a.sum() == 80);}{auto b = make_unique_lock(a, try_to_lock);if (b){a.withdraw(a.sum());assert(a.sum() == 0);a.show();}}return 0;}


4.2.Lock概念检查

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

 

4.3.Lock函数

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

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

 

Code:

 

mutex m1, m2;{auto g1 = make_unique_lock(m1, adopt_lock);auto g2 = make_unique_lock(m2, adopt_lock);lock(m1, m2);}//unique_lock自动解锁{auto g1 = make_unique_lock(m1, defer_lock);auto g2 = make_unique_lock(m2, defer_lock);try_lock(g1, g2);} //unique_lock自动解锁

5.补:Shared_mutex.

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


Code:

#include<iostream>#include<boost/thread/thread.hpp>#include<boost/chrono.hpp>#include<boost/bind.hpp>#include<boost/ref.hpp>using namespace std;using namespace boost;class rw_data{private:int m_x;shared_mutex rw_mu;public:rw_data() :m_x(0){}void write(){unique_lock<shared_mutex> g(rw_mu);++m_x;}void read(int &x){shared_lock<shared_mutex> g(rw_mu);x = m_x;}};mutex xzz;void writer(rw_data &d){for (int i = 0; i < 2; ++i){this_thread::sleep_for(chrono::microseconds(3000));d.write();}}void reader(rw_data &d){int x;for (int i = 0; i < 10; i++){this_thread::sleep_for(chrono::microseconds(5000));d.read(x);xzz.lock();cout << this_thread::get_id() << "reader:" << x << endl;xzz.unlock();}}int main(){//读写锁机制rw_data d;thread_group pool;pool.create_thread(bind(writer, boost::ref(d)));pool.create_thread(bind(writer, boost::ref(d)));pool.create_thread(bind(reader, boost::ref(d)));pool.create_thread(bind(reader, boost::ref(d)));pool.create_thread(bind(reader, boost::ref(d)));pool.create_thread(bind(reader, boost::ref(d)));pool.join_all();std::system("pause");return 0;}



0 0
原创粉丝点击