c++多线程 四----(互斥与锁 )

标准库支持互斥的形式包括互斥体(mutex)类和锁类。这些都可以实现同步。

互斥类: 

与互斥类都定义在<mutex>中,所以使用的话, 需要加载这个头文件

非定时的互斥体类:

std::mutex;  std::recursive_mutex;

 都支持下面的方法:

  • lock(): 调试线程将尝试获取锁,并且阻塞直到获得锁。这个方法会无限期的阻塞。如果希望设置线程阻塞的最长时间,应该使用定时的互斥体。
  • try_lock(): 调用线程将尝试获得锁,如果当前锁被其他线程持有,这个调用会立即返回。如过成功获得锁,try_lock()返回true,否则返回false。
  • unlock():释放由调用线程所持有的锁,使另一个线程能获得这个锁。

 定时的互斥体类:

std::timed_mutex   std::recursive_timed_mutex  std::shared_timed_mutex

  都支持下面的方法:支持普通的lock() , try_lock(),unlock()外还支持下面的方法:

  • try_lock_for(rel_time) 调用线程尝试在给定的相对时间内获得这个锁。如果在给定的时间超时之后就不能获得这个锁,这个调用失败并返回false,在时间内获得这个锁,这个调用成功后会返回true。
  • try_lock_until(abs_time):调用线程将尝试获得这个锁,直到系统时间等于或超过绝对时间,在时间内获得这个锁,这个调用成功后会返回true。如果在给定的时间超时之后就不能获得这个锁,失败并返回false

锁类 

std::lock_guard; std::unique_lock; std::shared_lock
  • lock_guard 是一个简单的锁。
  • unique_lock是一个复杂的锁,它允许将获得锁的时间延长到计算需要时,远在声明之后。使用owns_lock()方法可以确定是否获得了锁。
  • shared_lock 与unique_lock差不多,区别shared_lock 类在底层的共享互斥上调用与共享权的方法。获得的锁是共享锁。不是独占锁。

产考例子:就是第一个例子,改变下。

#include <mutex>  //互斥的变量
class CounterE
{
public:
	CounterE(int id, int numIterations)
		:mId(id), mNumIterations(numIterations)
	{
	}

	void operator ()() const
	{
		for (int i = 0; i < mNumIterations; ++i)
		{
			lock_guard<mutex> lock(mMutex);
			cout << "Counter " << mId << " has value ";
			cout << i << endl;
		}
	}
private:
	int mId;
	int mNumIterations;
	static mutex mMutex;
};
mutex CounterE::mMutex;


void testCounterE()
{
	//using uniform initialization syntax
	thread t1{ CounterE{ 1,20 } };
	//using named variable
	CounterE c(2, 12);
	thread t2(c);
	//using temporary
	thread t3(CounterE(3, 10));
	//wait for threads to finish
	t1.join();
	t2.join();
	t3.join();
}

 结果:

Counter 1 has value 0
Counter 1 has value 1
Counter 1 has value 2
Counter 1 has value 3
Counter 1 has value 4
Counter 1 has value 5
Counter 1 has value 6
Counter 1 has value 7
Counter 1 has value 8
Counter 1 has value 9
Counter 1 has value 10
Counter 1 has value 11
Counter 1 has value 12
Counter 1 has value 13
Counter 1 has value 14
Counter 1 has value 15
Counter 1 has value 16
Counter 1 has value 17
Counter 1 has value 18
Counter 1 has value 19
Counter 3 has value 0
Counter 3 has value 1
Counter 3 has value 2
Counter 3 has value 3
Counter 3 has value 4
Counter 3 has value 5
Counter 3 has value 6
Counter 3 has value 7
Counter 3 has value 8
Counter 3 has value 9
Counter 2 has value 0
Counter 2 has value 1
Counter 2 has value 2
Counter 2 has value 3
Counter 2 has value 4
Counter 2 has value 5
Counter 2 has value 6
Counter 2 has value 7
Counter 2 has value 8
Counter 2 has value 9
Counter 2 has value 10
Counter 2 has value 11

然后发现这次不乱了,但是是执行完一个后,在执行的下个线程,这样不是我们想要的结果。

于是采用时间锁,与时间互斥量。

把类改成:

class CounterE
{
public:
	CounterE(int id, int numIterations)
		:mId(id), mNumIterations(numIterations)
	{
	}

	void operator ()() const
	{
		for (int i = 0; i < mNumIterations; ++i)
		{
//			lock_guard<mutex> lock(mMutex);
			unique_lock<timed_mutex> lock(mMutex, 200ms);
			if (lock)
			{
				cout << "Counter " << mId << " has value ";
				cout << i << endl;
			}
		}
	}
private:
	int mId;
	int mNumIterations;
	static timed_mutex mMutex;
};
timed_mutex CounterE::mMutex;

输出结果:

Counter 1 has value 0
Counter 2 has value 0
Counter 3 has value 0
Counter 1 has value 1
Counter 2 has value 1
Counter 2 has value 2
Counter 1 has value 2
Counter 3 has value 1
Counter 3 has value 2
Counter 1 has value 3
Counter 2 has value 3
Counter 2 has value 4
Counter 2 has value 5
Counter 2 has value 6
Counter 2 has value 7
Counter 3 has value 3
Counter 1 has value 4
Counter 2 has value 8
Counter 3 has value 4
Counter 1 has value 5
Counter 2 has value 9
Counter 3 has value 5
Counter 1 has value 6
Counter 2 has value 10
Counter 3 has value 6
Counter 1 has value 7
Counter 2 has value 11
Counter 3 has value 7
Counter 1 has value 8
Counter 3 has value 8
Counter 1 has value 9
Counter 3 has value 9
Counter 1 has value 10
Counter 1 has value 11
Counter 1 has value 12
Counter 1 has value 13
Counter 1 has value 14
Counter 1 has value 15
Counter 1 has value 16
Counter 1 has value 17
Counter 1 has value 18
Counter 1 has value 19

 这样就不乱了,而且同时进行的线程,实现了最基本多线程同步的样子。也是大家想要的结果。

在线程中可以使用call_once,只执行一此后,才退出阻塞,让线程继续下去。

例子:

once_flag gOnceFlag;
void callNameOnce()
{
	cout << "the only call once" << endl;
}

class CounterE
{
public:
	CounterE(int id, int numIterations)
		:mId(id), mNumIterations(numIterations)
	{
	}

	void operator ()() const
	{
		for (int i = 0; i < mNumIterations; ++i)
		{
//			lock_guard<mutex> lock(mMutex);
			call_once(gOnceFlag, callNameOnce);
			unique_lock<timed_mutex> lock(mMutex, 200ms);
			if (lock)
			{
				cout << "Counter " << mId << " has value ";
				cout << i << endl;
			}
		}
	}
private:
	int mId;
	int mNumIterations;
	static timed_mutex mMutex;
};
timed_mutex CounterE::mMutex;

输出结果:

the only call once
Counter 3 has value 0
Counter 2 has value 0
Counter 1 has value 0
Counter 3 has value 1
Counter 3 has value 2
Counter 1 has value 1
Counter 2 has value 1
Counter 3 has value 3
Counter 1 has value 2
Counter 2 has value 2
Counter 3 has value 4
Counter 1 has value 3
Counter 2 has value 3
Counter 3 has value 5
Counter 1 has value 4
Counter 2 has value 4
Counter 3 has value 6
Counter 1 has value 5
Counter 2 has value 5
Counter 3 has value 7
Counter 1 has value 6
Counter 2 has value 6
Counter 2 has value 7
Counter 1 has value 7
Counter 3 has value 8
Counter 2 has value 8
Counter 1 has value 8
Counter 3 has value 9
Counter 2 has value 9
Counter 1 has value 9
Counter 2 has value 10
Counter 1 has value 10
Counter 2 has value 11
Counter 1 has value 11
Counter 1 has value 12
Counter 1 has value 13
Counter 1 has value 14
Counter 1 has value 15
Counter 1 has value 16
Counter 1 has value 17
Counter 1 has value 18
Counter 1 has value 19

我们惊奇的发现只执行了一次,其实就是让他执行一次,然后就不执行了。是不是非常有意思呢,第一章出现的问题也算解决了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值