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

//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_guard
mutex 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;
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值