C++多线程学习[四]:多线程的通信和同步、互斥锁、超时锁、共享锁

news2024/12/29 10:20:26

一、多线程的状态

  • 初始化 (Init):该线程正在被创建。
  • 就绪 (Ready):该线程在就绪列表中,等待CPU的调度。
  • 运行 (Running):该线程正在运行。
  • 阻塞(Blocked):该线程被阻塞挂起。Blocked状态包括:pend(锁、事件、信号量等阻塞)、suspend(主动pend)、delay(延时阻塞)、pendtime(因为锁、事件、信号量时间等超时等待)。
  • 退出(Exit):该线程运行结束,等待父线程后收其控制块资源。

在这里插入图片描述

二、多线程之间的竞争关系和临界区

1、竞争关系(Race condition)

多个线程同时读写共享资源
例如:

#include<iostream>
#include<thread>
#include<string>
using namespace std;
void Test()
{
	cout << "---------------" << endl;
	cout << "Test 1 " << endl;
	cout << "Test 2 " << endl;
	cout << "-----------------" << endl;
}

int main()
{
	for (int i = 0; i < 10; i++)
	{
		thread th(Test);
		th.detach();
	}
	getchar();
	return 0;
}

在这里插入图片描述

我们创建了10个线程,但是每个线程在运行时都是无规律的,对于相同的输出都是处于竞争状态。

2、临界区(Critical Section)

我们使用C++ 11 自带的mutex(互斥锁)来解决竞争状态。
在这里插入图片描述
原理:
当n个线程要访问我们临界区时,只允许一个线程进入,其余线程会阻塞在临界区外,每当一个线程运行完临界区代码后,会允许阻塞在临界区外的一个线程再次访问临界区。

3、lock()和try_lock()区别

  • lock():**lock 函数用于获取互斥锁。**如果当前互斥锁已被其他线程占用,则 lock 函数将阻塞当前线程,直到互斥锁可用为止。一旦成功获取到互斥锁,该线程将独占互斥锁,并可以继续执行后续的操作。在完成互斥锁所需的操作后,线程应该调用 unlock 函数来释放互斥锁,以便其他线程可以获取它。阻塞式的,会一直等待直到成功获取到互斥锁。

  • try_lock()try_lock 函数用于尝试获取互斥锁,但是它并不会阻塞当前线程。如果当前互斥锁可用,try_lock 函数将立即获取到互斥锁,并返回 true。如果当前互斥锁被其他线程占用,try_lock 函数将立即返回 false,而不会阻塞线程。通过检查返回值,线程可以根据情况选择等待或放弃获取互斥锁。非阻塞式的,立即返回获取互斥锁的结果,线程可以根据返回值做出相应的处理。
    例如:这里有10个线程,只有两个线程进入,而其它8个线程并不会阻塞住。
    在这里插入图片描述

  • 使用 lock 函数时要注意避免死锁的情况,而 try_lock 函数则可以更灵活地处理互斥锁的获取失败情况。

4、互斥锁的坑(线程抢占)

在这里插入图片描述
可以看到在这段代码中,本来1号线程运行完,执行unlock()后,应该其他阻塞的线程应该进入代码内,但是发现进入的依旧是1号ID的线程。
原因:当我们执行完unlock()后,因为代码执行速度就几微秒的时间,但是我们CPU调度探测一次得过一段时间,所以导致了这个问题。(也就是说我们执行的速度快于检测的速度,导致我们线程1号执行完后又再次进入循环,又把资源锁上了)
解决:只需要在unlock()后面等待一段时间就可以,让我们CPU有充裕的时间来调度检测。在这里插入图片描述

三、互斥锁(mutex)

上面样例中设计到这里就不在过多描述

四、超时锁(timed_mutex)

在这里插入图片描述
在这里插入图片描述

超时锁可以让阻塞的线程不断尝试进入,如果超过等待时间,就会执行日志结果,可以帮助我们更好的检查线程状态,检查是否超时或者是否存在死锁。

五、可重入锁(recursive_mutex)

1.可重入锁可以解决哪类情况?

如果直接用互斥锁在这里插入图片描述
显然会直接报错,因为我们要进入下一个锁内需要先解除当前锁在这里插入图片描述

显然是让人头疼麻烦的,我们必须每次得考虑解锁的时机。为了解决此类情况,我们有了可重入锁。

2.可重入锁。

在这里插入图片描述
功能如可以多重进入锁区域,要注意的是,进入几个锁就要在最后解除几个锁,这样才能让其他阻塞线程进入。

六、共享锁(shared_mutex)

C++ 14中引入了shared_timed_mutex;
C++ 17中引入了shared_mutex;

1、 共享锁的功能

假设有6个线程同时要访问同一片区域数据,有5个线程要读数据,而有一个线程要写数据,那么共享锁可以让读线程的5个线程同时进行读,然后阻塞写数据的线程。当写线程进入时,阻塞5个读的线程,写线程开始写数据。这就是共享锁的基本作用。

2、代码

#include<iostream>
#include<thread>
#include<shared_mutex>
using namespace std;
shared_mutex smux;
int num;
void thread_read(int i)
{
	for (;;)
	{
	smux.lock_shared();
	cout << "num is :" <<num<< endl;
	this_thread::sleep_for(1000ms);
	smux.unlock_shared();
	this_thread::sleep_for(10ms);
	}
}
void thread_write(int i)
{
	for (;;)
	{
	smux.lock_shared();
	num++;
	cout << "add num" << endl;
	this_thread::sleep_for(1000ms);
	smux.unlock_shared();
	this_thread::sleep_for(10ms);
	}

}

int main()
{
	for (int i = 0; i < 5; i++)
	{
		thread th(thread_read,i + 1);
		this_thread::sleep_for(50ms);
		th.detach();
	}
	for (int i = 0; i < 2; i++)
	{
		thread th(thread_write, i + 1);
		this_thread::sleep_for(50ms);
		th.detach();
	}
	getchar();
	return 0;
}

在这里插入图片描述

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

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

相关文章

AI智能化办公:巧用ChatGPT高效搞定Excel数据分析

文章目录 1. 自动提取关键信息2. 自动生成分析报告3. 自动回答问题4. 自动生成图表《巧用ChatGPT高效搞定Excel数据分析》关键点内容简介作者简介 《AI智能化办公&#xff1a;ChatGPT使用方法与技巧从入门到精通》图书特色内容简介作者简介 随着人工智能技术的不断发展&#xf…

【服务器数据恢复】服务器迁移数据时lun数据丢失的数据恢复案例

服务器数据恢复环境&服务器故障&#xff1a; 一台安装Windows操作系统的服务器。工作人员在迁移该服务器中数据时突然无法读取数据&#xff0c;服务器管理界面出现报错。经过检查发现服务器中一个lun的数据丢失。 服务器数据恢复过程&#xff1a; 1、将故障服务器中所有磁盘…

Java 10_000 代表什么意思? 数字里面混夹着下划线?

先放一张图 &#xff0c;这到底是sleep了多久&#xff1f; public static void main(String[] args) {int a 10_000; System.out.println(a); // 10000} java 7 的 特性 &#xff1a;https://docs.oracle.com/javase/7/docs/technotes/guides/language/underscores-literals…

开发需求总结9-el-tree获取选中节点,节点全选时返回被全选子级的父节点,未全选则返回被选中的节点

目录 需求描述 代码实现&#xff1a; 需求描述 需要获取树组件选中的节点&#xff0c;假如父节点被选中&#xff08;该节点全选&#xff09;&#xff0c;即只返回父节点的数据&#xff0c;如父节点未被全选&#xff0c;则正常返回被选中节点的数据。 示例一&#xff1a; 如上图…

未来科技五年人工智能行业产业发展趋势最新竞争力

人工智能&#xff08;Artificial Intelligence&#xff0c;AI&#xff09;是近年来快速发展的热门领域&#xff0c;被广泛应用于各个行业。随着技术的不断创新和突破&#xff0c;人工智能行业的竞争力也在不断提升。本文将分析未来科技五年人工智能行业产业发展趋势&#xff0c…

群发邮件的免费软件?做外贸用什么邮箱好?

群发邮件的免费软件有哪些&#xff1f;好用的邮件群发软件&#xff1f; 在数字时代&#xff0c;邮件已成为人们沟通的主要方式之一。有时候&#xff0c;我们需要给大量的联系人发送信息&#xff0c;这时候&#xff0c;群发邮件就显得格外重要。接下来蜂邮就来探讨一下那些值得…

基于springboot的疫情物资捐赠和分配系统

&#x1f345;点赞收藏关注 → 私信领取本源代码、数据库&#x1f345; 本人在Java毕业设计领域有多年的经验&#xff0c;陆续会更新更多优质的Java实战项目希望你能有所收获&#xff0c;少走一些弯路。&#x1f345;关注我不迷路&#x1f345;一 、设计说明 1.1 课题背景 二…

2024年-最强DXF图色纯脚本开源-by剑道书生

1.此项目截止更新2024年1月10日 项目功能 1.未央搬砖 2.未央圆桌 3.白图搬砖 4.自动登录 5.未央拍卖 6.刷畅玩每日 7.洗票 8.魔化 9.换票 10.拍卖辟邪玉和玉荣 11.自动入库 12.自动换号 13.替换玉荣 等一系列功能 代码行数约17000行左右,源码开源出来仅供大家学习研究不可用于…

群晖启动SSH功能【无法执行此操作,可能是因为网络连接不稳定或系统正忙】的解决方案

修改了SSH配置导致SSH服务无法启动或者其它操作导致的SSH服务无法启动 解决方案&#xff1a;控制面板-任务计划-新增任务 附上命令: bash sudo cp /etc.defaults/ssh/sshd_config /etc/ssh这个命令是用默认的ssh配置覆盖掉当前的ssh配置 添加任务后不要勾选前面的启动&#x…

长春数字孪生元宇宙赋能工业智能制造,助力制造业企业数字化转型

长春数字孪生元宇宙赋能工业智能制造&#xff0c;助力制造业企业数字化转型。随着科技的不断发展&#xff0c;数字化转型已经成为制造业企业发展的必然趋势。长春市作为我国重要的工业基地之一&#xff0c;积极探索数字化转型的新路径&#xff0c;将数字孪生元宇宙技术应用于工…

牛客周赛 Round 5 解题报告 | 珂学家 | 思维场

前言 剑&#xff0c;和茶一样&#xff0c;只有细细品味&#xff0c;才能理解它的风雅。 整体评价 挺难的一场比赛&#xff0c;C题差点点错科技树(想着用Dsu On Tree), D题开始上难度&#xff0c;但是只是分析其实就是一个区间求交集的脑筋急转弯&#xff0c;E题盲猜是菊花图。…

如何在企业微信开发者中心使用内网穿透工具回调本地接口服务

文章目录 1. Windows安装Cpolar2. 创建Cpolar域名3. 创建企业微信应用4. 定义回调本地接口5. 回调和可信域名接口校验6. 设置固定Cpolar域名7. 使用固定域名校验 企业微信开发者在应用的开发测试阶段&#xff0c;应用服务通常是部署在开发环境&#xff0c;在有数据回调的开发场…

婴儿洗衣机哪款性价比高?希亦、RUUFFY、觉飞全维度测评对比

当婴儿的到来&#xff0c;确实会给家庭带来许多变化&#xff0c;就好比如对于宝宝相关衣物的清洗需求。对于新生儿及婴幼儿的衣服&#xff0c;一般都要给予特殊的照顾与清洗&#xff0c;以保证不含细菌及过敏原。尤其是刚刚出生的婴儿&#xff0c;这时候宝宝们的皮肤很是幼嫩。…

【Dynamo学习笔记】基础入门

目录 前言1 Dynamo的界面2 节点的操作3 几何形体的创建与编辑3.1 几何形体的创建3.1.1 直线3.1.2 圆形3.1.3 多边形3.1.4 长方体3.1.5 球体 3.2 几何形体的编辑3.2.1 坐标点的平移复制3.2.2 几何形体的平移复制3.2.3 几何形体的镜像复制3.2.4 几何形体的旋转复制3.2.5 几何形体…

YOLOv8改进 | 主干篇 | EfficientViT高效的特征提取网络完爆MobileNet系列(轻量化网络结构)

一、本文介绍 本文给大家带来的改进机制是主干网络,一个名字EfficientViT的特征提取网络(和之前发布的只是同名但不是同一个),其基本原理是提升视觉变换器在高效处理高分辨率视觉任务的能力。它采用了创新的建筑模块设计,包括三明治布局和级联群组注意力模块。其是一种高效率…

如何利用SQL创建RFM用户分析模型

RFM用户分析模型究竟是什么&#xff1f;在之前的博客已经介绍了它的意义以及如何在现有的数据的情况下&#xff0c;利用Pandas创建分析模型&#xff0c;这里不再重复&#xff0c;详细可以参考我博客https://blog.csdn.net/weixin_48591974/article/details/116192534 这一期将详…

记一次用Qt开发 “启动器” 的经历

项目背景 背景 工具多&#xff0c;需要频繁切换。Windows环境&#xff0c;因为日常用到的软件较多&#xff0c;大致如下 浏览器涉及3款 FirefoxChromeEdge 开发的编译器及IDE涉及 Visual StudioVisual Studio CodePycharmSublime Text 设备涉及 DeskTopMackbook AirNoteBook…

【linux】查看Debian应用程序图标对应的可执行命令

在Debian系统中&#xff0c;应用程序图标通常与.desktop文件关联。您可以通过查看.desktop文件来找到对应的可执行命令。这些文件通常位于/usr/share/applications/或~/.local/share/applications/目录下。这里是如何查找的步骤&#xff1a; 1. 打开文件管理器或终端。 2. 导…

linux下485通信调试记录

1、使用linux下使用串口调试助手 linux下可以安装并使用下述串口调试工具进行串口测试&#xff1a; 1.1、cutecom cutecom是linux下常用的图形化串口调试软件&#xff0c;通过以下命令安装并打开&#xff1a; sudo apt-get install cutecom sudo cutecom显示如下&#xff1…

DAY01_Spring—Spring框架介绍IOCSpring工厂模式

目录 1 什么是框架2 Spring框架2.1 Spring介绍2.2 MVC模型说明2.3 IOC思想2.3.1 问题说明2.3.2 IOC说明 3 Spring IOC具体实现3.1 环境准备3.1.1 关于JDK说明3.1.2 检查JDK环境配置 3.2 创建项目3.3 关于Maven 命令3.3.1 install 命令3.3.2 clean 命令 3.4 添加jar包文件3.4.1 …