<二>线程间互斥-mutex互斥锁和lock_guard
多线程程序
竞态条件:多线程程序执行的结果是一致的,不会随着CPU对线程不同的调用顺序而产生不同的运行结果.
解决?:互斥锁 mutex
经典的卖票问题,三个线程卖100张票
代码1
#include <iostream>
#include <thread>
#include <list>
#include <mutex>
int ticketCount = 100;
std::mutex mtx;//互斥锁
void sellTicket(int window) {
while (ticketCount > 0) {
mtx.lock();
std::cout << "窗口" << window << "销售" << ticketCount << std::endl;
ticketCount--;
mtx.unlock();
std::this_thread::sleep_for(std::chrono::milliseconds(50));
}
}//end
int main() {
std::list<std::thread> tlist;
for (int i = 0; i < 3; i++) {
tlist.push_back(std::thread(sellTicket,i));
}
for (std::thread & t : tlist) {
t.join();
}
system("pause");
return 0;
}
上面代码的问题...
while (ticketCount > 0) {
mtx.lock();
std::cout << "窗口" << window << "销售" << ticketCount << std::endl;
ticketCount--;
mtx.unlock();
std::this_thread::sleep_for(std::chrono::milliseconds(50));
}
如果ticketCount =1 ,当前有一个线程A while (ticketCount > 0)为true,线程A还没执行ticketCount--完成时,cpu交给了线程B
线程B while (ticketCount > 0)也为true,进入 循环体内,造成了买0号票,改进如下
代码2
#include <iostream>
#include <thread>
#include <list>
#include <mutex>
int ticketCount = 100;
std::mutex mtx;//互斥锁
void sellTicket(int window) {
while (ticketCount > 0) {
mtx.lock();
if(ticketCount >0){
std::cout << "窗口" << window << "销售" << ticketCount << std::endl;
ticketCount--;
}
mtx.unlock();
std::this_thread::sleep_for(std::chrono::milliseconds(50));
}
}//end
int main() {
std::list<std::thread> tlist;
for (int i = 0; i < 3; i++) {
tlist.push_back(std::thread(sellTicket,i));
}
for (std::thread & t : tlist) {
t.join();
}
system("pause");
return 0;
}
代码2还有些问题!! 如下
mtx.lock();
代码
代码
代码
代码
.....
mtx.unlock();
如果在代码lock()和unlock()之间 非常返回,导致mtx没有正常unlock(),那么出现死锁问题 =》智能指针 lock_gurad unique_lock
看lock_gurad
#include <iostream>
#include <thread>
#include <list>
#include <mutex>
int ticketCount = 100;
std::mutex mtx;//互斥锁
void sellTicket(int window) {
while (ticketCount > 0) {
{
std::lock_guard<std::mutex> lock(mtx);
std::cout << "窗口" << window << "销售" << ticketCount << std::endl;
ticketCount--;
std::this_thread::sleep_for(std::chrono::milliseconds(50));
}
}
}//end
int main() {
std::list<std::thread> tlist;
for (int i = 0; i < 3; i++) {
tlist.push_back(std::thread(sellTicket,i));
}
for (std::thread & t : tlist) {
t.join();
}
system("pause");
return 0;
}
上面的图片中我们知道lock_gurad 的拷贝构造函数被关闭了,所以当我们遇到函数调用需要拷贝构造lock_guard的时候,就有障碍了,这个时候可以用unique_lock
unique_lock 转移指针,支持带右值得拷贝赋值,支持参数传递拷贝构造的,他的左值的拷贝构造也是被关闭了 看下图
<二>线程间互斥-mutex互斥锁和lock_guard的更多相关文章
- java 并发性和多线程 -- 读感 (二 线程间通讯,共享内存的机制)
参考文章:http://ifeve.com/java-concurrency-thread-directory/ 其中的竞态,线程安全,内存模型,线程间的通信,java ThreadLocal类小节部 ...
- 【转】JAVA 并发性和多线程 -- 读感 (二 线程间通讯,共享内存的机制)
原文地址:https://www.cnblogs.com/edenpans/p/6020113.html 参考文章:http://ifeve.com/java-concurrency-thread-d ...
- 【原】iOS多线程之线程间通信和线程互斥
线程间通信 1> 线程间通信分为两种 主线程进入子线程(前面的方法都可以) 子线程回到主线程 2> 返回主线程 3> 代码 这个案例的思路是:当我触摸屏幕时,会在子线程加载图片,然后 ...
- Linux/Unix 线程同步技术之互斥量(1)
众所周知,互斥量(mutex)是同步线程对共享资源访问的技术,用来防止下面这种情况:线程A试图访问某个共享资源时,线程B正在对其进行修改,从而造成资源状态不一致.与之相关的一个术语临界区(critic ...
- 深入学习c++--多线程编程(二)【当线程间需要共享非const资源】
1. 遇到的问题 #include <iostream> #include <thread> #include <chrono> #include <futu ...
- Windows环境下多线程编程原理与应用读书笔记(4)————线程间通信概述
<一>线程间通信方法 全局变量方式:进程中的线程共享全局变量,可以通过全局变量进行线程间通信. 参数传递法:主线程创建子线程并让子线程为其服务,因此主线程和其他线程可以通过参数传递进行通信 ...
- java多线程详解(6)-线程间的通信wait及notify方法
Java多线程间的通信 本文提纲 一. 线程的几种状态 二. 线程间的相互作用 三.实例代码分析 一. 线程的几种状态 线程有四种状态,任何一个线程肯定处于这四种状态中的一种:(1). 产生(New) ...
- python线程间通信
#!/usr/bin/python # -*- coding:utf8 -*- from threading import Thread, Lock import random def test_th ...
- linux c 线程间同步(通信)的几种方法--互斥锁,条件变量,信号量,读写锁
Linux下提供了多种方式来处理线程同步,最常用的是互斥锁.条件变量.信号量和读写锁. 下面是思维导图: 一.互斥锁(mutex) 锁机制是同一时刻只允许一个线程执行一个关键部分的代码. 1 . ...
- 2种方式(线程间通信/互斥锁)实现两个线程,一个线程打印1-52,另一个线程打印字母A-Z,打印顺序为12A34B56C......5152Z
//2019/06/13 本周HT面试遇到的问题,答得不是很好,自己重新做一下.面试只需要写出线程间通信的方式,//我当时大致知道思路,因为之前看过马士兵老师的多线程视频,但是代码写出来估计编译都是报 ...
随机推荐
- [题解] Atcoder ABC 213 H Stroll DP,分治FFT
题目 令\(dp_{i,j}\)表示从点1到达点i,路径长度为j的方案数.转移为\(dp_{i,j}=\sum_{(i,v,w)\in E}dp_{v,j-w}p_{i,v,w}\). 显然只能从长度 ...
- Java实现6种常见排序
1.冒泡排序(Bubble Sort) 第0轮 3 1 4 1 5 9 2 6 5 3 5 8 9 第1轮 1 3 1 4 5 2 6 5 3 5 8 9 9 第2轮 1 1 3 4 2 5 5 3 ...
- POJ1985 Cow Marathon (树的直径)
用两次dfs求出树的直径,这两次dfs可以写在一起,当然为了方便理解,这里是分开写的. 1 //两次dfs求树的重心 2 #include<cstdio> 3 #include<cs ...
- P8548 小挖的买花 方法记录
原题链接 小挖的买花 题目背景 小挖喜欢买花,但是 ta 太懒了!所以这个任务全权交给了你. 题目描述 花店里只有 \(n\) 株花,每一株花都有三个属性:价格 \(cost_i\).美丽度 \(be ...
- ysoserial commonscollections6 分析
利用链如下: 其中LazyMap.get()->ChainedTransformer.transform()-InvokerTransformer.transform()与CC1链一致. /* ...
- Rdt2.1 和 Rdt2.2的详细解释
Rdt2.1 和 Rdt2.2的详细解释 目录 Rdt2.1 和 Rdt2.2的详细解释 这俩为啥会出现? 解决之道 Rdt 2.1 Rdt2.2 可靠数据传递中Rdt1.0, Rdt2.0, Rdt ...
- LOJ2325「清华集训 2017」小Y和恐怖的奴隶主
题目链接 首先dp很显然,\(f(i,s)\)表示到了第i轮,各种血量人数的情况为s今后的期望攻击boss次数.那么有\(f(i,s)=\frac{1}{num+1}*\sum_{s->s'}( ...
- JDBC数据库编程(java实训报告)
文章目录 一.实验要求: 二.实验环境: 三.实验内容: 1.建立数据库连接 2.查询数据 2.1 测试结果 3.添加数据 3.1.测试结果 4.删除数据 4.1.测试结果 5.修改数据 5.1 测试 ...
- 知识图谱-生物信息学-医学顶刊论文(Bioinformatics-2022)-SGCL-DTI:用于DTI预测的监督图协同对比学习
14.(2022.5.21)Bioinformatics-SGCL-DTI:用于DTI预测的监督图协同对比学习 论文标题: Supervised graph co-contrastive learni ...
- python的list,dict,set
list # 1.list() 把可迭代对象转换成list,即for循环遍历的可迭代对象 my_str = "abcdef" new_list = list(my_str) pri ...