<二>线程间互斥-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面试遇到的问题,答得不是很好,自己重新做一下.面试只需要写出线程间通信的方式,//我当时大致知道思路,因为之前看过马士兵老师的多线程视频,但是代码写出来估计编译都是报 ...
随机推荐
- GitLab 之 PlantUML 的配置及使用
转载自:https://cloud.tencent.com/developer/article/1010617 1.PlantUML介绍 UML 统一建模语言是一个通用的可视化建模语言,用于对软件进行 ...
- 货币转换I
A=input() if A[0] in ['U','u']: RMB=(eval(A[3:]))*6.78 print("RMB{:.2f}".format(RMB)) else ...
- 使用css制作轮播图
<!--HTML代码--> <!DOCTYPE html> <html lang="en"><head> <meta char ...
- 两将军问题和TCP三次握手
两将军问题,又被称为两将军悖论.两军问题, 是一个经典的计算机思想实验. 首先, 为避免混淆,我们需要认识到两将军问题虽然与拜占庭将军问题相关,但两者不是一个东西.拜占庭将军问题是一个更通用的两将军问 ...
- spring boot使用swagger生成api接口文档
前言 在之前的文章中,使用mybatis-plus生成了对应的包,在此基础上,我们针对项目的api接口,添加swagger配置和注解,生成swagger接口文档 具体可以查看本站spring boot ...
- 关于多个 Kubernetes 集群指标的采集操作
简介 在使用观测云期间,有时需要针对一个工作空间接入多个 Kubernetes 集群指标,通过观测云提供的全局 Tag 的方式来进行区分,大大提高了效率.下面是我总结的操作步骤. 当集群中只有一个采集 ...
- Linux系统安装宝塔面板教程
# Linux系统宝塔安装教程 注意:安装宝塔面板的前提条件 首先要有一台服务器或者使用linux系统的虚拟机. 安装前请确保是[全新的机器].必须是没装过其它环境的新系统,如Apache/Nginx ...
- 齐博X1-栏目的调用2
fun('sort@fathers',$fid,'cms') 获取上层多级栏目这样的,比如我们现在所属第三级栏目,现在可以利用这个函数获取第二级和第一级的栏目,当然自身也会被调用出来,所以此函数用的 ...
- Spring Retry 重试
重试的使用场景比较多,比如调用远程服务时,由于网络或者服务端响应慢导致调用超时,此时可以多重试几次.用定时任务也可以实现重试的效果,但比较麻烦,用Spring Retry的话一个注解搞定所有.话不多说 ...
- js判断手机系统是android还是ios?
var u = navigator.userAgent; //识别各种浏览器 var isAndroid = u.indexOf('Android') > -1 || u.indexOf('Ad ...