多线程程序

竞态条件:多线程程序执行的结果是一致的,不会随着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的更多相关文章

  1. java 并发性和多线程 -- 读感 (二 线程间通讯,共享内存的机制)

    参考文章:http://ifeve.com/java-concurrency-thread-directory/ 其中的竞态,线程安全,内存模型,线程间的通信,java ThreadLocal类小节部 ...

  2. 【转】JAVA 并发性和多线程 -- 读感 (二 线程间通讯,共享内存的机制)

    原文地址:https://www.cnblogs.com/edenpans/p/6020113.html 参考文章:http://ifeve.com/java-concurrency-thread-d ...

  3. 【原】iOS多线程之线程间通信和线程互斥

    线程间通信 1> 线程间通信分为两种 主线程进入子线程(前面的方法都可以) 子线程回到主线程 2> 返回主线程 3> 代码 这个案例的思路是:当我触摸屏幕时,会在子线程加载图片,然后 ...

  4. Linux/Unix 线程同步技术之互斥量(1)

    众所周知,互斥量(mutex)是同步线程对共享资源访问的技术,用来防止下面这种情况:线程A试图访问某个共享资源时,线程B正在对其进行修改,从而造成资源状态不一致.与之相关的一个术语临界区(critic ...

  5. 深入学习c++--多线程编程(二)【当线程间需要共享非const资源】

    1. 遇到的问题 #include <iostream> #include <thread> #include <chrono> #include <futu ...

  6. Windows环境下多线程编程原理与应用读书笔记(4)————线程间通信概述

    <一>线程间通信方法 全局变量方式:进程中的线程共享全局变量,可以通过全局变量进行线程间通信. 参数传递法:主线程创建子线程并让子线程为其服务,因此主线程和其他线程可以通过参数传递进行通信 ...

  7. java多线程详解(6)-线程间的通信wait及notify方法

    Java多线程间的通信 本文提纲 一. 线程的几种状态 二. 线程间的相互作用 三.实例代码分析 一. 线程的几种状态 线程有四种状态,任何一个线程肯定处于这四种状态中的一种:(1). 产生(New) ...

  8. python线程间通信

    #!/usr/bin/python # -*- coding:utf8 -*- from threading import Thread, Lock import random def test_th ...

  9. linux c 线程间同步(通信)的几种方法--互斥锁,条件变量,信号量,读写锁

    Linux下提供了多种方式来处理线程同步,最常用的是互斥锁.条件变量.信号量和读写锁. 下面是思维导图:  一.互斥锁(mutex)  锁机制是同一时刻只允许一个线程执行一个关键部分的代码. 1 . ...

  10. 2种方式(线程间通信/互斥锁)实现两个线程,一个线程打印1-52,另一个线程打印字母A-Z,打印顺序为12A34B56C......5152Z

    //2019/06/13 本周HT面试遇到的问题,答得不是很好,自己重新做一下.面试只需要写出线程间通信的方式,//我当时大致知道思路,因为之前看过马士兵老师的多线程视频,但是代码写出来估计编译都是报 ...

随机推荐

  1. GitLab 之 PlantUML 的配置及使用

    转载自:https://cloud.tencent.com/developer/article/1010617 1.PlantUML介绍 UML 统一建模语言是一个通用的可视化建模语言,用于对软件进行 ...

  2. 货币转换I

    A=input() if A[0] in ['U','u']: RMB=(eval(A[3:]))*6.78 print("RMB{:.2f}".format(RMB)) else ...

  3. 使用css制作轮播图

    <!--HTML代码--> <!DOCTYPE html> <html lang="en"><head> <meta char ...

  4. 两将军问题和TCP三次握手

    两将军问题,又被称为两将军悖论.两军问题, 是一个经典的计算机思想实验. 首先, 为避免混淆,我们需要认识到两将军问题虽然与拜占庭将军问题相关,但两者不是一个东西.拜占庭将军问题是一个更通用的两将军问 ...

  5. spring boot使用swagger生成api接口文档

    前言 在之前的文章中,使用mybatis-plus生成了对应的包,在此基础上,我们针对项目的api接口,添加swagger配置和注解,生成swagger接口文档 具体可以查看本站spring boot ...

  6. 关于多个 Kubernetes 集群指标的采集操作

    简介 在使用观测云期间,有时需要针对一个工作空间接入多个 Kubernetes 集群指标,通过观测云提供的全局 Tag 的方式来进行区分,大大提高了效率.下面是我总结的操作步骤. 当集群中只有一个采集 ...

  7. Linux系统安装宝塔面板教程

    # Linux系统宝塔安装教程 注意:安装宝塔面板的前提条件 首先要有一台服务器或者使用linux系统的虚拟机. 安装前请确保是[全新的机器].必须是没装过其它环境的新系统,如Apache/Nginx ...

  8. 齐博X1-栏目的调用2

    fun('sort@fathers',$fid,'cms')  获取上层多级栏目这样的,比如我们现在所属第三级栏目,现在可以利用这个函数获取第二级和第一级的栏目,当然自身也会被调用出来,所以此函数用的 ...

  9. Spring Retry 重试

    重试的使用场景比较多,比如调用远程服务时,由于网络或者服务端响应慢导致调用超时,此时可以多重试几次.用定时任务也可以实现重试的效果,但比较麻烦,用Spring Retry的话一个注解搞定所有.话不多说 ...

  10. js判断手机系统是android还是ios?

    var u = navigator.userAgent; //识别各种浏览器 var isAndroid = u.indexOf('Android') > -1 || u.indexOf('Ad ...