博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
创建多个线程、互斥量、死琐
阅读量:6311 次
发布时间:2019-06-22

本文共 3689 字,大约阅读时间需要 12 分钟。

创建多个线程

#include
#include
#include
using namespace std;void print(int i){ cout<<"子线程"<
<<"开始"<
myThreads; for(int i=0; i<10; i++) myThreads.push_back(thread(print,i)); for(auto iter = myThreads.begin(); iter!=myThreads.end(); ++iter) { iter->join(); } cout<<"主线程结束"<

由下图可以看出多个线程的执行是不确定的,和操作系统对线程的调度有关。

此处输入图片的描述

互斥量 多线程保护共享数据

问题:一个线程往队列内插入数据,另一个线程往队列内取数据,在没有保护措施的情况下,此时的程序是不稳定的。

措施:采取使用互斥的方法保护共享数据

#include
#include
#include
#include
using namespace std;class A{public: void input() { for(int i=0;i<100000;i++) { cout<<"插入元素"<
<
msg;};int main(){ A myobja; thread insert_thread(&A::input,&myobja); thread pop_thread(&A::output,&myobja); insert_thread.join(); pop_thread.join(); cout<< "线程执行完成" <

互斥量的用法

1.lock(),unlook()

先lock、共享数据、unlock

成对使用

void input(){    for(int i=0;i<100000;i++)    {        my_mutex.lock();  //加锁        cout<<"插入元素"<<

2.模板类std::lock_guard

可取代lock、unlock()

void output(){    lock_guard
guard(my_mutex); /* 构造函数里调用look() 析构函数里调用unlook() 缺点:不够灵活 */ for(int i=0;i<100000;i++) { if(msg.empty()) cout<<"队列为空"<

死琐

A等B,B等A或者有一个互等的循环

产生死锁

#include
#include
#include
#include
#include
using namespace std;class A{public: void input() { my_mutex1.lock(); for(int i=0;i<1000000;i++) i=i; /* 其他程序 */ my_mutex2.lock(); my_mutex1.unlock(); my_mutex2.unlock(); } void output() { my_mutex2.lock(); for(int i=0;i<1000000;i++) i=i; /* 其他程序 */ my_mutex1.lock(); my_mutex1.unlock(); my_mutex2.unlock(); }private: list
msg; mutex my_mutex1; ///互斥量1 mutex my_mutex2; ///互斥量2};int main(){ A myobja; thread insert_thread(&A::input,&myobja); thread pop_thread(&A::output,&myobja); insert_thread.join(); pop_thread.join(); cout<< "线程执行完成" <

此处输入图片的描述

上面程序进程一把一号锁锁住等待二号锁
上面程序进程二把二号锁锁住等待一号锁
产生互相等待

解决方案,保持调用顺序一致理论上不会死锁

std::lock()

一次锁住两个或以上的互斥量

如果失败则一个都不锁,要么全都锁住。从而避免死琐的问题

std::lock_guard的std::adopt_lock参数

lock_guard (mutex_type& m, adopt_lock_t tag);

lock_guard 对象管理 Mutex 对象 m,与 locking 初始化(1) 不同的是, Mutex 对象 m 已被当前线程锁住。

lock_guard
guard(my_mutex1,std::adopt_lock_t);

std::unique_lock

std::unique_lock 的构造函数的数目相对来说比 std::lock_guard 多,其中一方面也是因为 std::unique_lock 更加灵活,从而在构造 std::unique_lock 对象时可以接受额外的参数。

参数 功能
默认构造函数 新创建的 unique_lock 对象不管理任何 Mutex 对象。
locking 新创建的 unique_lock 对象管理 Mutex 对象 m,并尝试调用 m.lock() 对 Mutex 对象进行上锁,如果此时另外某个 unique_lock 对象已经管理了该 Mutex 对象 m,则当前线程将会被阻塞。
try-locking 新创建的 unique_lock 对象管理 Mutex 对象 m,并尝试调用 m.try_lock() 对 Mutex 对象进行上锁,但如果上锁不成功,并不会阻塞当前线程。
deferred 新创建的 unique_lock 对象管理 Mutex 对象 m,但是在初始化的时候并不锁住 Mutex 对象。 m 应该是一个没有当前线程锁住的 Mutex 对象。
adopting 新创建的 unique_lock 对象管理 Mutex 对象 m, m 应该是一个已经被当前线程锁住的 Mutex 对象。(并且当前新创建的 unique_lock 对象拥有对锁(Lock)的所有权)。
locking一段时间(duration) 新创建的 unique_lock 对象管理 Mutex 对象 m,并试图通过调用 m.try_lock_for(rel_time) 来锁住 Mutex 对象一段时间(rel_time)。
locking直到某个时间点(time point) 新创建的 unique_lock 对象管理 Mutex 对象m,并试图通过调用 m.try_lock_until(abs_time) 来在某个时间点(abs_time)之前锁住 Mutex 对象。
拷贝构造 [被禁用] unique_lock 对象不能被拷贝构造。
移动(move)构造 新创建的 unique_lock 对象获得了由 x 所管理的 Mutex 对象的所有权(包括当前 Mutex 的状态)。调用 move 构造之后, x 对象如同通过默认构造函数所创建的,就不再管理任何 Mutex 对象了。

综上所述,由 (2) 和 (5) 创建的 unique_lock 对象通常拥有 Mutex 对象的锁。而通过 (1) 和 (4) 创建的则不会拥有锁。通过 (3),(6) 和 (7) 创建的 unique_lock 对象,则在 lock 成功时获得锁。

转载于:https://www.cnblogs.com/xcantaloupe/p/10395361.html

你可能感兴趣的文章
React Native最佳学习模版- F8 App开源了
查看>>
云服务正在吞噬世界!
查看>>
阅读Android源码的一些姿势
查看>>
Web语义化标准解读
查看>>
一份代码构建移动、桌面、Web全平台应用
查看>>
高性能 Lua 技巧(译)
查看>>
区分指针、变量名、指针所指向的内存
查看>>
异步编程的世界
查看>>
最近话题火爆的四件事你知道不?
查看>>
SpringBoot整合MyBatis
查看>>
云计算产业如何率先推行信用管理?
查看>>
Android 类库书签更新(一)
查看>>
Unity3D Input按键系统
查看>>
简单的一条SQL,不简单的做事思维 NOT IN 、NOT EXISTS、LEFT JOIN用法差别 ...
查看>>
DataWorks:任务未运行自助排查
查看>>
ionic/cordova热部署
查看>>
「镁客早报」特斯拉裁员,马斯克解释没有办法;微软推出Azure DevOps赏金计划...
查看>>
centos 7.4 使用 pgxc_ctl 安装与使用
查看>>
Redis 单key值过大 优化方式
查看>>
【数据库】表分区
查看>>