C++11之多线程(二)

本文介绍了C++11中互斥对象管理类模板的加锁策略,包括std::lock_guard、std::unique_lock和std::shared_lock,并讨论了如何避免对多个互斥对象加锁时的死锁问题。通过示例代码展示了使用std::lock和std::try_lock函数来确保线程安全和避免死锁,强调了这些操作的异常安全性。
摘要由CSDN通过智能技术生成

二, 互斥对象和锁

    互斥(Mutex::Mutual Exclusion)
    下面的代码中两个线程连续的往int_set中插入多个随机产生的整数
#include <thread>
#include <set>
#include <random>

using namespace std;

int main()
{
	std::set<int> int_set;
	auto f = [&int_set](){
		try
		{
			std::random_device rd;
			std::mt19937 gen(rd());
			std::uniform_int_distribution<> dis(1, 1000);
			for (std::size_t i = 0; i != 100000; ++i)
			{
				int_set.insert(dis(gen));
				cout << dis(gen) << endl;
			}
		}
		catch (...)
		{

		}
	};

	std::thread td1(f), td2(f);
	td1.join();
	td2.join();

	getchar();
	return 0;
}

        由于std::set::insert不是多线程安全的,多个线程同时对同一个对象调用insert其行为是未定义的(通常导致的结果是程序崩溃)。因此需要一种机制在此处对多个线程进行同步,保证任一时刻至多有一个线程在调用insert函数。
        C++11提供了4个互斥对象(C++14提供了一个)用于同步多个线程对共享资源的访问。

        锁(Lock)
    这里的锁是动词而非名词,互斥对象的主要操作有两个,加锁(lock)和释放锁(unlock)。当一个线程对互斥对象进行lock操作并成功获得这个互斥对象的所有权,在此线程对此对象unlock前,其他线程对这个互斥对象的lock操作都会被阻塞。修改前面的代码在两个线程中对共享资源int_set执行insert操作前先对互斥对象mt进行加锁操作,待操作完成后再释放锁。这样就能保证同一时刻至多只有一个线程对int_set对象执行insert操作。
#include <thread>
#include <set>
#include <random>
#include <mutex>

using namespace std;

int main()
{
	std::mutex mt;
	std::set<int> int_set;
	auto f = [&int_set, &mt](){
		try
		{
			std::random_device rd;
			std::mt19937 gen(rd());
			std::uniform_int_distribution<> dis(1, 1000);
			for (std::size_t i = 0; i != 100000; ++i)
			{
				mt.lock();
				int_set.insert(dis(gen));
				mt.unlock();
				cout << dis(gen) << endl;
			}
		}
		catch (...)
		{

		}
	};

	std::thread td1(f), td2(f);
	td1.join();
	td2.join();

	getchar();
	return 0;
}

        使用RAII管理互斥对象
        在使用锁时应避免发生死锁。前面的代码倘若一个线程在执行int_set.insert时抛出异常,会导致unlock不被执行,
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值