【C++11/线程相关】thread类编写多线程、mutex互斥锁和lock_guard、atomic原子类型

目录

  • 通过thread类编写C++多线程程序
  • 线程间互斥——mutex互斥锁和lock_guard
    • mutex互斥锁
    • lock_guard
  • 线程间通信
    • C++11实现生产者与消费者模型
  • 基于CAS操作的atomic原子类型

橙色

通过thread类编写C++多线程程序

为什么结果没有子线程中所打印的字符串呢?因为通过detach进行了线程分离,即主线程不会等待子线程结束再继续往下运行,而是直接运行到底,所以主线程运行完直接结束了。而子线程是睡眠了两秒后才打印语句,此时主线程已经结束,也就看不到该语句了

#include<stdio.h>
#include<iostream>
#include<thread>
using namespace std;
/*
线程内容:
一.怎么创建启动一个线程
std::thread定义一个线程对象,传入线程所需要的线程函数和参数,线程自动开启t.join():等待t线程结束,当前线程继续往下运行
t.detach():把t线程设置为分离线程,主线程结束,整个进程结束,所有子线程都自动结束了
*/
void threadHandele1(int time)
{//让子线程睡眠2秒std::this_thread::sleep_for(std::chrono::seconds(time));cout << "hello thread1!" << endl;
}int main(){//创建了一个线程对象,传入一个线程函数,新线程就开始运行了thread t1(threadHandele1,2);//主线程等待子线程结束,主线程继续往下运行//t1.join(); //把子线程设置为分离线程t1.detach();cout << "main thread done!" << endl;return 0;
}

在这里插入图片描述

线程间互斥——mutex互斥锁和lock_guard

mutex互斥锁

很值得注意的是锁+双重判断的应用。为什么要在锁上后再加上一个if语句判断呢?因为如果不加的话,当ticketCount=1时,第一个线程拿到锁,开始执行,但此时可能还没执行到ticketCount–,所以其他子线程也进入while循环,并在mtx.lock()处阻塞,此时第一个线程卖出票了并释放锁,于是已经进入while循环的第二个线程开始拿锁执行,就容易出现卖出第0张票,卖出第-1张票的情况,所以在拿到锁后再加入一个if语句判断是十分有必要的

#include<stdio.h>
#include<iostream>
#include<thread>
#include<mutex>
#include<list>
using namespace std;
/*
C++ thread 模拟车站三个窗口卖票的程序
*/
int ticketCount = 100;//车站有100张票,由三个窗口一起卖票
std::mutex mtx;//全局的一把互斥锁 //模拟卖票的线程函数
void sellTicket(int index)
{   while(ticketCount>0)//ticketCount=1  锁+双重判断{mtx.lock();if(ticketCount>0){cout << "窗口:" << index << "卖出第:" << ticketCount <<"张票"<< endl;ticketCount--;}mtx.unlock();std::this_thread::sleep_for(std::chrono::milliseconds(100));   } 
}int main()
{list<std::thread> tlist;for (int i = 1; i <= 3;++i){tlist.push_back(std::thread(sellTicket, i));}for(std::thread &t:tlist){t.join();}cout << "所有窗口卖票结束!" << endl;return 0;
}

lock_guard

lock_guard是一个模板类

#include<stdio.h>
#include<iostream>
#include<thread>
#include<mutex>
#include<list>
using namespace std;
/*
C++ thread 模拟车站三个窗口卖票的程序
*/
int ticketCount = 100;//车站有100张票,由三个窗口一起卖票
std::mutex mtx;//全局的一把互斥锁 //模拟卖票的线程函数
void sellTicket(int index)
{   while(ticketCount>0)//ticketCount=1  锁+双重判断{      {//出了{}作用域就会析构自动释放mtx这把锁,保证所有线程都能释放锁//防止死锁问题的发生lock_guard<std::mutex> lock(mtx);if(ticketCount>0){cout << "窗口:" << index << "卖出第:" << ticketCount <<"张票"<< endl;ticketCount--;}}std::this_thread::sleep_for(std::chrono::milliseconds(100));      }  
}int main()
{list<std::thread> tlist;for (int i = 1; i <= 3;++i){tlist.push_back(std::thread(sellTicket, i));}for(std::thread &t:tlist){t.join();}cout << "所有窗口卖票结束!" << endl;return 0;
}

在这里插入图片描述

线程间通信

C++11实现生产者与消费者模型

#include <mutex>
#include <condition_variable>
#include <queue> //C++ STL里面的所有容器都不是线程安全的
#include <iostream>
#include <thread>using namespace std;class Queue
{
public:void put(int val) // 生产者{unique_lock<std::mutex> lck(mtx);while (!que.empty()){// que不为空,生产者应该通知消费者去消费// 生产者应该进入 #1等待状态 #2并把mtx互斥锁释放掉cv.wait(lck);}que.push(val);cv.notify_all(); // 通知其他所有消费者可以进行消费了//其他线程的得到通知就会从等待状态 ==> 阻塞状态 ==> 获取互斥锁才能继续执行cout << "生产者生产:" << val << "号物品" << endl;}int get() // 消费者{unique_lock<std::mutex> lck(mtx);while (que.empty()){// 消费者线程发现que是空的,通知生产者线程生产物品// #1 进入等待状态 #2把互斥锁mutex释放掉cv.wait(lck);}int val = que.front();que.pop();cv.notify_all(); //通知其他所有生产者可以进行生产了cout << "消费者消费: " << val << "号物品" << endl;return val;}private:queue<int> que;mutex mtx;             // 定义互斥锁,做线程间的胡吃操作condition_variable cv; // 定义条件变量,做线程之间的同步通信操作
};void producer(Queue *que) // 生产者线程
{for (int i = 1; i <= 10; ++i){que->put(i);std::this_thread::sleep_for(std::chrono::milliseconds(100));}
}void consumer(Queue *que) // 消费者线程
{for (int i = 1; i <= 10; ++i){que->get();std::this_thread::sleep_for(std::chrono::milliseconds(100));}
}int main()
{Queue que; // 两个线程共享的队列thread t1(producer, &que);thread t2(consumer, &que);t1.join();t2.join();
}

在这里插入图片描述

unique_lock与lock_guard的比较,仔细看下面的代码和注释

#include <bits/stdc++.h>
#include <mutex>
#include <condition_variable>using namespace std;std::mutex mtx;
std::condition_variable cv;int main()
{/**** 唤醒在cv上等待的线程* 其他在cv上等待的线程收到通知,从等待状态 ==> 阻塞状态 ==> 获得互斥锁 ==> 线程继续向下执行* **/// cv.notify_all();// 它不仅可以用在简单的临界区代码段的互斥操作中,还能用于函数调用过程中unique_lock<std::mutex> lck(mtx);cv.wait(lck); // #两个作用:1使线程进入等待状态 2 lck.unlock()可以把mutex释放掉// 不可以用在函数参数传递或者返回过程中,只能用在简单的临界区代码段的互斥操作中lock_guard<std::mutex> guard(mtx);// mtx.lock();// mtx.unlock();return 0;
}

基于CAS操作的atomic原子类型

如果mycount不是原子类型的话,最后的值很可能就不会是1000了

#include <iostream>
#include <thread>
#include<atomic>
#include<list>
using namespace std;atomic_bool isReady;
atomic_int mycount;void task()
{while(!isReady){this_thread::yield();//线程出让当前的cpu时间片,等待下一次调度}for (int i = 0; i < 100;i++){mycount++;}
}int main()
{list<std::thread> tlist;isReady=false;mycount = 0;for (int i = 0; i < 10;i++){tlist.push_back(std::thread(task));}this_thread::sleep_for(chrono::seconds(3));isReady = true;for(thread &t:tlist){t.join();}cout << "mycount:" << mycount << endl;
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/195316.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

代码随想录算法训练营 ---第五十三天

第一题&#xff1a; 简介&#xff1a; 本题和昨天的最大重复子串问题很相似&#xff0c;只不过本题不一定是连续的。 动规五部曲分析如下&#xff1a; 确定dp数组&#xff08;dp table&#xff09;以及下标的含义 dp[i][j]&#xff1a;长度为i-1 的字符串text1与长度为j-1的…

Vue实现图片预览(Viewer.js)

摘要&#xff1a; vue项目开发中遇到一个图片预览的需求&#xff0c;可以切换下一张&#xff0c;就是花里胡哨的&#xff0c;所以找viewer.js的插件 npm install v-viewer -S在项目main.js中加入&#xff1a; Viewer.setDefaults用于更改默认配置&#xff0c;比如我不想要显示…

嘴尚绝卤味:健康卤味,未来餐饮市场的新星

随着人们生活水平的提高&#xff0c;对于吃的要求也越来越高。尤其是在快节奏的现代社会中&#xff0c;健康饮食成为了越来越多人的追求。在这种背景下&#xff0c;健康卤味这一新兴食品品类应运而生&#xff0c;成为了餐饮市场的新宠儿。 一、健康卤味的崛起 传统的卤味制作过…

内容过滤算法:构建数字世界的守护者

目录 引言 1. 内容过滤算法概述 2. 内容过滤算法的分类 2.1 关键词过滤算法 2.2 统计模型 2.3 机器学习算法 2.4 深度学习算法 3. 内容过滤算法在实际应用中的体现 3.1 电子邮件过滤 3.2 社交媒体内容过滤 3.3 网络搜索引擎 4. 内容过滤算法的挑战与未来发展 4.1 对…

编程题:电话号码

&#x1f4d1;打牌 &#xff1a; da pai ge的个人主页 &#x1f324;️个人专栏 &#xff1a; da pai ge的博客专栏 ☁️宝剑锋从磨砺出&#xff0c;梅花香自苦寒来 &#x1f4d1;题目解析 这个题目比较…

【文献阅读】Joint Demosaicing and Denoising with Self Guidance

1. 摘要 近年来&#xff0c;一些神经网络在联合去马赛克和去噪(JDD)方面表现出了良好的效果。大多数算法首先将Bayer原始图像分解为四通道RGGB图像&#xff0c;然后将其输入神经网络。这种做法忽略了一个事实&#xff0c;即绿色通道的采样率是红色和蓝色通道的两倍。在本文中&…

自定义注解验证数据字典选项及bean注入问题

我们在工作中经常需要对字典选项进行定义&#xff0c;如果客户端传来的字典项不符合要求&#xff0c;那么根本无法保存&#xff0c;但是已有的注解并没有字典值的验证&#xff0c;那我们就自己实现一个 一、自定义字典值验证的注解DictValid import javax.validation.Constra…

pycharm 创建vue并实现简易路由功能

使用pycharm创建vue项目时&#xff0c;选择vite来创建vue。为什么使用vite&#xff1f;因为vite是专门针对vue开发的打包框架&#xff0c;以前使用vue-cli来创建vue项目&#xff0c;就是使用的webpack来进行打包的&#xff0c;现在有了vite&#xff0c;就尽量使用vite来创建vue…

备战春招——12.3 算法

哈希表 哈希表主要是使用 map、unordered_map、set、unorerdered_set、multi_&#xff0c;完成映射操作&#xff0c;主要是相应的函数。map和set是有序的&#xff0c;使用的是树的形式&#xff0c;unordered_map和unordered_set使用的是散列比表的&#xff0c;无序。 相应函数…

RabbitMQ 消息中间件 消息队列

RabbitMQ1、RabbitMQ简介 RabbiMQ是⽤Erang开发的&#xff0c;集群⾮常⽅便&#xff0c;因为Erlang天⽣就是⼀⻔分布式语⾔&#xff0c;但其本身并不⽀持负载均衡。支持高并发&#xff0c;支持可扩展。支持AJAX&#xff0c;持久化&#xff0c;用于在分布式系统中存储转发消息&a…

福德植保无人机案例:无人机种地的那些事儿

大家好&#xff0c;今天我要给大家介绍一个非常有趣的案例&#xff0c;那就是我们的福德植保无人机工厂。这个工厂可不简单&#xff0c;它可是无人机植保领域的佼佼者&#xff0c;让我们一起来看看他们的故事吧&#xff01;首先&#xff0c;让我们来了解一下无人机植保这个概念…

ROS-ROS通信机制-话题通信

文章目录 一、话题通信基础知识二、话题通信基本操作2-1 C2-2 Python2-3 C与python节点通信 三、自定义msg3-1 自定义msg3-2 C实现自定义msg调用3-3 Python实现自定义msg调用 一、话题通信基础知识 话题通信实现模型是比较复杂的&#xff0c;该模型如下图所示,该模型中涉及到三…

Kubernetes(K8s) Ingress介绍-08

Ingress介绍 在前面课程中已经提到&#xff0c;Service对集群之外暴露服务的主要方式有两种&#xff1a;NotePort和LoadBalancer&#xff0c;但是这两种方式&#xff0c;都有一定的缺点&#xff1a; NodePort方式的缺点是会占用很多集群机器的端口&#xff0c;那么当集群服务…

中级工程师评审条件:如何成为一名合格的中级工程师

作为一名工程师&#xff0c;不仅需要具备扎实的技术基础和实践能力&#xff0c;还需要通过评审来证明自己的能力水平。在成为一名合格的中级工程师之前&#xff0c;你需要满足一系列评审条件。甘建二今天将详细介绍中级工程师评审的要求和标准&#xff0c;帮助你成为更优秀的工…

树_左叶子之和

//给定二叉树的根节点 root &#xff0c;返回所有左叶子之和。 // // // // 示例 1&#xff1a; // // // // //输入: root [3,9,20,null,null,15,7] //输出: 24 //解释: 在这个二叉树中&#xff0c;有两个左叶子&#xff0c;分别是 9 和 15&#xff0c;所以返回 24 //…

geoserver维度time

postgis创建date类型的字段 写入测试数据&#xff0c;对应flag&#xff0c;flag有不同的样式&#xff0c;这样方便观测 geoserver发布图层的时候设置“维度”启用 测试&#xff0c;设置了根据flag展示不同的颜色

外卖平台推荐算法的优化与实践

目录 引言 一、推荐算法的原理 二、推荐算法的挑战 三、实际案例分析 四、优化推荐算法的策略 五、结论 引言 在当今数字化社会&#xff0c;外卖平台成为了人们生活中不可或缺的一部分。为了提供更加个性化、高效的服务&#xff0c;外卖平台使用推荐算法成为了一项关键技…

深度学习算法:探索人工智能的前沿

目录 引言 第一部分&#xff1a;深度学习的基础 1.1 什么是深度学习&#xff1f; 1.2 神经网络的演化 第二部分&#xff1a;深度学习的关键技术 2.1 卷积神经网络&#xff08;CNN&#xff09; 2.2 循环神经网络&#xff08;RNN&#xff09; 2.3 长短时记忆网络&#xf…

python自学之《艾伯特用Python做科学计算》(1)——(待完善)

好吧&#xff0c;刚开始就打了一波而广告 啄木鸟社区的Python图书概览&#xff1a; http://wiki.woodpecker.org.cn/moin/PyBooks &#xff08;22/388&#xff09;

ASP.NET 网上选课系统的设计与实现

1 系统设计与实现 1.1 数据库设计 为充分保护数据的一致性&#xff0c;数据库中各表都规范化设计&#xff0c;下图是系统数据库中使用的表以及各表之间的关系&#xff1a; 下面就各个表分别给出说明&#xff1a; (1)课程基本信息&#xff08;CourseInfo&#xff09;表&#x…