多线程程序

竞态条件:多线程程序执行的结果是一致的,不会随着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. Docker安装集群rabbitMQ

    环境准备 Centos 7.5虚拟机三台: 192.168.102.128 192.168.102.130 192.168.102.131 以上虚拟机统一安装docker环境 三台机器分别配置如下所示 ...

  2. 手把手教你使用LabVIEW OpenCV DNN实现手写数字识别(含源码)

    @ 目录 前言 一.OpenCV DNN模块 1.OpenCV DNN简介 2.LabVIEW中DNN模块函数 二.TensorFlow pb文件的生成和调用 1.TensorFlow2 Keras模 ...

  3. POJ2728 Desert King (最小生成树、0/1分数规划)

    显然的0/1分数规划问题,用二分来解决,检验mid,就用prim算法求最小生成树,看总边权是否大等于0即可验证. 1 #include<bits/stdc++.h> 2 using nam ...

  4. Spring 深入——IoC 容器 01

    IoC容器的实现学习--01 目录 IoC容器的实现学习--01 简介 IoC 容器系列的设计与实现:BeanFactory 和 ApplicationContext BeanFactory load ...

  5. gradle项目对比maven项目的目录架构以及对gradle wrapper的理解

    转载请注明出处: 1.使用 idea 搭建 gradle项目 注意 type 选择 gradle 以及 language 选择 grooy                       搭建后的项目架构 ...

  6. jsp页面中怎么利用a标签的href进行传递参数以及需要注意的地方

    jsp页面中: <a href="${pageContext.request.contextPath }/infoController/getProductInfo?productId ...

  7. GitLab CI/CD 自动化部署入门

    前言:因为找了B站内推,测试开发,正好知道内部使用GitLab做自动化测试,所以简单学了一下,有错误的地方请指正. 入门 初始化 cp: 无法获取'/root/node-v12.9.0-linux-x ...

  8. 字符串匹配(BF算法和KMP算法及改进KMP算法)

    #include <stdio.h> #include <string.h> #include <stdlib.h> #include<cstring> ...

  9. java中的垃圾回收算法与垃圾回收器

    常用的垃圾回收算法 标记-清除 标记清除算法是一种非移动式的回收算法,分为标记 清除 2个阶段,简而言之就是先标记出需要回收的对象,标记完成后再回收掉所有标记的内存对象,如下图 可见回收后图中被标记的 ...

  10. pta第二次博客

    目录 pta第二次博客 1.前言 2.设计与分析 第四次作业第一题 第四次作业第一题 第四次作业第一题 第四次作业第一题 pta第二次博客 1.前言 2.设计与分析 第四次作业第一题 1.题目: &q ...