【c++高级篇】--多任务编程/多线程(Thread)
目录
1.进程和线程的概念:
1.1 进程(Process):
1.2线程(Thread):
1.3 对比总结:
2.多线程编程:
2.1 基于线程的多任务处理(Thread):
2.1.1. mbed.h 中的线程类
2.2 注意事项:(死锁)
2.2.1. 进程死锁
2.2.2 线程死锁
2.2.3 避免死锁(Thread):
1.进程和线程的概念:
进程和线程是操作系统中两个重要的概念,它们之间存在着密切的关系,但有不同的特性和用途。
1.1 进程(Process):
- 操作系统中资源分配的最小单位,每个进程拥有独立的内存空间、系统资源(文件描述符、网络连接等)和生命周期。进程之间相对独立,无法直接共享彼此的内存空间。
进程虽然无法直接共享彼此内存空间 ,但是操作系统提供了一些机制,使得进程之间可以共享或交换部分资源,但这些共享和通信需要通过特殊的手段实现,而不是像线程那样直接访问共享的内存空间。
进程间资源共享的常用方式:
-
管道(Pipe):允许一个进程将数据写入管道,另一个进程从管道中读取,用于单向通信。
-
消息队列(Message Queue):操作系统提供的一种数据结构,用于在多个进程之间发送和接收消息,实现异步通信。
-
共享内存(Shared Memory):一种特殊的内存区域,多个进程可以映射到这个区域来进行数据共享。共享内存速度快,但需要借助信号量等同步机制,避免数据竞争。
-
信号量(Semaphore):用来控制对共享资源的访问,防止多个进程同时访问导致冲突。
-
套接字(Socket):尤其用于分布式系统中,通过网络通信实现跨进程的数据共享和传递。
1.2线程(Thread):
- 是操作系统中CPU调度的最小单位。线程共享同一进程的内存空间和系统资源,可以认为是进程中的“轻量级”执行单元。同一进程中的线程之间能够共享全局变量和数据,通讯成本低。
1.3 对比总结:
2.多线程编程:
多线程是多任务处理的一种特殊形式,多任务处理允许让电脑同时运行两个或两个以上的程序。在一般情况下,有两种类型的多任务处理:基于进程和基于线程。
-
基于进程的多任务处理:每个进程都有自己的内存空间和系统资源,进程之间相对独立,切换开销较大,但安全性高。每个进程可以运行不同的程序,相互之间的通信通常需要更复杂的机制,比如进程间通信(IPC)。
-
基于线程的多任务处理:线程是进程内的一个执行单元,多个线程共享同一进程的内存空间和资源,因此切换开销相对较小,适合需要频繁进行上下文切换的任务。由于共享内存,线程间的通信更为高效,但也带来了同步和安全性的问题。
2.1 基于线程的多任务处理(Thread):
以嵌入式单片为例,在mbed OS
中,mbed.h
库提供了对线程的支持,使得在嵌入式系统中可以方便地实现多线程。
2.1.1. mbed.h
中的线程类
在mbed.h
库中,线程主要通过 Thread
类来管理和操作。该类提供了创建、启动、暂停、恢复和终止线程的基本操作方法。
常用的 Thread
类方法有:
Thread::start(callback)
:启动线程,执行指定的回调函数。Thread::join()
:阻塞当前线程,直到其被调用线程完成。(顺序执行),调用join()
后,主线程会被阻塞,直到子线程执行完毕。Thread::terminate()
:强制终止线程的执行。Thread::yield()
:让出CPU,使其他线程有机会运行。Thread::sleep_for(milliseconds)
:使线程在指定的毫秒数内休眠。
#include "mbed.h"// 定义LED灯
DigitalOut led1(LED1);
DigitalOut led2(LED2);// 定义线程
Thread thread1;
Thread thread2;// 线程函数1 - 控制LED1闪烁
void led1_thread() {while (true) {led1 = !led1; // 切换LED1的状态ThisThread::sleep_for(500ms); // 每500ms切换一次}
}// 线程函数2 - 控制LED2闪烁
void led2_thread() {while (true) {led2 = !led2; // 切换LED2的状态ThisThread::sleep_for(1000ms); // 每1000ms切换一次}
}int main() {// 启动线程thread1.start(led1_thread);thread2.start(led2_thread);// 主线程可以执行其他任务,或等待子线程结束thread1.join();thread2.join();
}
2.2 注意事项:(死锁)
进程死锁和线程死锁都涉及资源的相互等待,导致无法继续执行。
2.2.1. 进程死锁
进程死锁发生在两个或多个进程之间。当进程A持有资源1并等待资源2,而进程B持有资源2并等待资源1时,两个进程将永远处于等待状态,无法继续执行。
特征
-
互斥:资源只能被一个进程占用。(不同同时访问)
-
持有并等待:进程在持有至少一个资源的情况下,申请其他资源。
-
不剥夺:已经分配给进程的资源在其完成之前不能被强制剥夺。
-
循环等待:存在一种进程资源的循环等待关系。
示例
进程A持有资源R1,并请求资源R2。 进程B持有资源R2,并请求资源R1。
2.2.2 线程死锁
定义
在多线程程序中,线程死锁通常发生在多个线程尝试以不同的顺序获取多个锁时。例如,线程1持有锁A并等待锁B,而线程2持有锁B并等待锁A,这将导致两个线程永远处于等待状态。
特征
-
与进程死锁相似,同样具有互斥、持有并等待、不剥夺和循环等待的特征。
-
线程死锁通常更复杂,因为线程之间的锁依赖关系可能更难以追踪
2.2.3 避免死锁(Thread):
同步和锁
同步指的是在多个线程之间协调它们的执行顺序,以确保某些操作以特定的顺序完成,防止出现竞态条件(race condition)。同步的目的在于确保共享资源的安全访问。
方法:同步可以通过多种方式实现,包括:
- 互斥锁(Mutex):保证在某一时刻只有一个线程可以访问某个资源。
- 信号量(Semaphore):控制同时访问某个资源的线程数量。
- 条件变量(Condition Variable):使线程在某些条件不满足时阻塞,直到条件满足。
- 读写锁(Read-Write Lock):允许多个线程同时读数据,但在写数据时需要独占访问。
互斥锁(Mutex):
#include "mbed.h"Mutex mutex; // 创建一个互斥锁
int sharedResource = 0; // 共享资源void threadTask() {for (int i = 0; i < 5; i++) {mutex.lock(); // 加锁,开始访问共享资源sharedResource++; // 修改共享资源printf("线程 %d 修改共享资源: %d\n", ThisThread::get_id(), sharedResource);mutex.unlock(); // 解锁,释放共享资源ThisThread::sleep_for(500ms);}
}int main() {Thread thread1;Thread thread2;thread1.start(threadTask);thread2.start(threadTask);thread1.join();thread2.join();printf("最终共享资源值: %d\n", sharedResource);return 0;
}
- 互斥锁(
mutex
)确保在同一时刻只有一个线程可以访问和修改sharedResource
,避免了数据竞争。 - 每个线程在修改共享资源前调用
mutex.lock()
,完成后调用mutex.unlock()
,以确保资源安全。
读写锁(Read-Write Lock):
#include "mbed.h"RWLock rwLock; // 创建读写锁
int sharedData = 0; // 共享数据// 读线程
void readTask() {for (int i = 0; i < 5; i++) {rwLock.lock_read(); // 获取读锁printf("读线程 %d 读取共享数据: %d\n", ThisThread::get_id(), sharedData);rwLock.unlock_read(); // 释放读锁ThisThread::sleep_for(500ms);}
}// 写线程
void writeTask() {for (int i = 0; i < 3; i++) {rwLock.lock_write(); // 获取写锁sharedData++; // 更新共享数据printf("写线程 %d 更新共享数据: %d\n", ThisThread::get_id(), sharedData);rwLock.unlock_write(); // 释放写锁ThisThread::sleep_for(1000ms);}
}int main() {Thread readThreads[5];Thread writeThread;// 启动多个读线程for (int i = 0; i < 5; i++) {readThreads[i].start(readTask);}// 启动一个写线程writeThread.start(writeTask);// 等待所有线程完成for (int i = 0; i < 5; i++) {readThreads[i].join();}writeThread.join();printf("所有任务完成\n");return 0;
}
-
多个读线程(
readTask
)同时读取共享数据sharedData
。由于使用了读写锁,多个读线程可以并行地访问共享数据。 -
写线程(
writeTask
)在更新共享数据时,必须获取写锁,这会阻止其他线程(无论是读线程还是写线程)访问共享数据,直到写操作完成。
相关文章:

【c++高级篇】--多任务编程/多线程(Thread)
目录 1.进程和线程的概念: 1.1 进程(Process): 1.2线程(Thread): 1.3 对比总结: 2.多线程编程: 2.1 基于线程的多任务处理(Thread)…...

【力扣专题栏】两数相加,如何实现存储在链表中的整数相加?
题解目录 1、题目描述解释2、算法原理解析3、代码编写(原始版本)4、代码编写(优化版本) 1、题目描述解释 2、算法原理解析 3、代码编写(原始版本) /*** Definition for singly-linked list.* struct ListN…...

SOLID - 接口隔离原则(Interface Segregation Principle)
SOLID - 接口隔离原则(Interface Segregation Principle) 定义 接口隔离原则(Interface Segregation Principle,ISP)是面向对象设计中的五个基本原则之一,通常缩写为SOLID中的I。这一原则由Robert C. Martin提出&…...
arrylist怎么让他变得不可修改
在Java中,要将一个 ArrayList变得不可修改,你可以使用以下几种方法: ###1. 使用 Collections.unmodifiableList Java 提供了 Collections.unmodifiableList 方法,可以生成一个不可修改的视图。这种方式返回的列表将不允许添加、…...
SpringMVC实战(3):拓展
四、RESTFul风格设计和实战 4.1 RESTFul风格概述 4.1.1 RESTFul风格简介 RESTful(Representational State Transfer)是一种软件架构风格,用于设计网络应用程序和服务之间的通信。它是一种基于标准 HTTP 方法的简单和轻量级的通信协议&…...
Vue应用中使用xlsx库实现Excel文件导出的完整指南
Vue应用中使用xlsx库实现Excel文件导出的完整指南 在现代Web开发中,经常需要将数据导出为Excel文件,以便于用户进行离线分析或记录。Vue.js作为一个轻量级且高效的前端框架,结合xlsx库可以轻松实现这一功能。本文将详细介绍如何在Vue应用中使…...

【数据分析】Power BI的使用教程
目录 1 Power BI架构1.1 Power BI Desktop1.2 Power BI服务1.3 Power BI移动版 2 Power Query2.1 Power Query编辑器2.2 Power Query的优点2.3 获取数据2.4 数据清洗的常用操作2.4.1 提升标题2.4.2 更改数据类型2.4.3 删除错误/空值2.4.4 删除重复项2.4.5 填充2.4.6 合并列2.4.…...
融合ASPICE与敏捷开发:探索汽车软件开发的最佳实践
ASPICE(Automotive SPICE,即汽车软件过程改进和能力dEtermination)与敏捷开发在软件开发领域各自具有独特的价值和特点,它们之间的关系可以归纳为既相互区别又相互补充。 一、ASPICE的特点 ASPICE是汽车行业对软件开发流程的一个评…...

后台管理系统的通用权限解决方案(三)SpringBoot整合Knife4j生成接口文档
1 Knife4j介绍 knife4j是为Java MVC框架集成Swagger生成Api文档的增强解决方案,前身是swagger-bootstrap-ui,取名knife4j是希望它能像一把匕首一样小巧,轻量,并且功能强悍! 其底层是对Springfox的封装,使…...

保研考研机试攻略:python笔记(1)
🐨🐨🐨宝子们好呀 ~ 我来更新欠大家的python笔记了,从这一篇开始我们来学下python,当然,如果只是想应对机试并且应试语言以C和C为主,那么大家对python了解一点就好,重点可以看高分篇…...

在浏览器中运行 Puppeteer:解锁新能力
Puppeteer,这个强大的浏览器自动化工具,通常在Node.js环境中运行。但你有没有想过,在浏览器本身中运行Puppeteer会是什么样子?这不仅能让我们利用Puppeteer的功能完成更多任务,还能避开Node.js特定的限制。 支持的功…...

Kafka消费者故障,出现活锁问题如何解决?
大家好,我是锋哥。今天分享关于【Kafka消费者故障,出现活锁问题如何解决?】面试题?希望对大家有帮助; Kafka消费者故障,出现活锁问题如何解决? 1000道 互联网大厂Java工程师 精选面试题-Java资…...

pytorch 交叉熵损失函数 BCELoss
BCE Loss 交叉熵损失函数计算公式: BCE Loss - 1/n*(y_actual * log(y_pred) (1 - y_actual) * log(1 - y_pred)) t[i]为标签值:0或者1 o[i]是经过sigmoid后的概率值 BCEWithLogitsLoss 这个损失将Sigmoid层和BCELoss合并在一个类中。 BCEWithLog…...
【进阶】面向对象之接口(多学三招)
文章目录 IDK8开始接口中新增的方法1.允许在接口中定义默认方法,需要使用关键字default修饰2.接口中的默认方法的定义格式3.接口中默认方法的注意事项总结 IDK8开始接口中新增的方法 JDK7以前:接口中只能定义抽象方法。JDK8的新特性:接口中可以定义有方法体的方法。(默认、静态…...
linux上trace code的几种方法
我们在看代码时,总是会遇到下面问题: 1.查看某个场景下的代码执行流 2.查看某个函数被执行时的routine 但是,如果直接查看源码,源码可能代码量大,且分支多,不容易理清。就需要让相关程序运行起来查看。 …...

文件操作(1) —— 文件基础知识
目录 1. 为什么使用文件? 2. 文件种类【按功能分】 3. 文件名 4. 数据文件种类【按存储方式细分】 5. 文件的打开和关闭 5.1 流和标准流 5.2 文件指针 5.3 文件的打开和关闭函数 6. 文件缓冲区 1. 为什么使用文件? 如果没有⽂件,我…...

4K双模显示器7款评测报告
4K双模显示器7款评测报告 HKC G27H7Pro 4K双模显示器 ROG华硕 XG27UCG 4K双模显示器 雷神 ZU27F160L 4K双模显示器 泰坦军团 P275MV PLUS 4K双模显示器 外星人(Alienware)AW2725QF 4K双模显示器 SANC盛色 D73uPro 4K双模显示器 ANTGAMER蚂蚁电竞 …...
2024.10.24华为(留学生)笔试题解
第一题集装箱堆叠 看注释即可 // 看题目,是最长连续序列的变种。底应该选大的,然后往上堆叠选择次大的(越接近底越好?) // 后续想一下,像是动态规划? // 再一想,好像排序后很容易处理#include <bits/stdc++.h> #include <functional> using namespace st…...

基于neo4j的医疗问诊系统
当你身体不适时,想要找到准确的答案却经常遇到模棱两可的答复,糟心吗?现在,基于neo4j的智能医疗问诊系统为你带来全新体验!我们设计了一个具备自动化问答功能的医疗系统,帮助用户快速获取专业的健康知识答案…...

java :String 类
在我们之前的讲解中我们已经了解了很多的Java知识,这节我们讲Java中字符如何定义以及关于String如何使用还有常见的string函数。 【本节目标】 1. 认识 String 类 2. 了解 String 类的基本用法 3. 熟练掌握 String 类的常见操作 4. 认识字符串常量池 5. 认识 …...

日语AI面试高效通关秘籍:专业解读与青柚面试智能助攻
在如今就业市场竞争日益激烈的背景下,越来越多的求职者将目光投向了日本及中日双语岗位。但是,一场日语面试往往让许多人感到步履维艰。你是否也曾因为面试官抛出的“刁钻问题”而心生畏惧?面对生疏的日语交流环境,即便提前恶补了…...

大话软工笔记—需求分析概述
需求分析,就是要对需求调研收集到的资料信息逐个地进行拆分、研究,从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要,后续设计的依据主要来自于需求分析的成果,包括: 项目的目的…...

AI Agent与Agentic AI:原理、应用、挑战与未来展望
文章目录 一、引言二、AI Agent与Agentic AI的兴起2.1 技术契机与生态成熟2.2 Agent的定义与特征2.3 Agent的发展历程 三、AI Agent的核心技术栈解密3.1 感知模块代码示例:使用Python和OpenCV进行图像识别 3.2 认知与决策模块代码示例:使用OpenAI GPT-3进…...

大型活动交通拥堵治理的视觉算法应用
大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动(如演唱会、马拉松赛事、高考中考等)期间,城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例,暖城商圈曾因观众集中离场导致周边…...
java 实现excel文件转pdf | 无水印 | 无限制
文章目录 目录 文章目录 前言 1.项目远程仓库配置 2.pom文件引入相关依赖 3.代码破解 二、Excel转PDF 1.代码实现 2.Aspose.License.xml 授权文件 总结 前言 java处理excel转pdf一直没找到什么好用的免费jar包工具,自己手写的难度,恐怕高级程序员花费一年的事件,也…...

基于当前项目通过npm包形式暴露公共组件
1.package.sjon文件配置 其中xh-flowable就是暴露出去的npm包名 2.创建tpyes文件夹,并新增内容 3.创建package文件夹...

【JavaWeb】Docker项目部署
引言 之前学习了Linux操作系统的常见命令,在Linux上安装软件,以及如何在Linux上部署一个单体项目,大多数同学都会有相同的感受,那就是麻烦。 核心体现在三点: 命令太多了,记不住 软件安装包名字复杂&…...

MySQL 知识小结(一)
一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库,分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷,但是文件存放起来数据比较冗余,用二进制能够更好管理咱们M…...

打手机检测算法AI智能分析网关V4守护公共/工业/医疗等多场景安全应用
一、方案背景 在现代生产与生活场景中,如工厂高危作业区、医院手术室、公共场景等,人员违规打手机的行为潜藏着巨大风险。传统依靠人工巡查的监管方式,存在效率低、覆盖面不足、判断主观性强等问题,难以满足对人员打手机行为精…...

从 GreenPlum 到镜舟数据库:杭银消费金融湖仓一体转型实践
作者:吴岐诗,杭银消费金融大数据应用开发工程师 本文整理自杭银消费金融大数据应用开发工程师在StarRocks Summit Asia 2024的分享 引言:融合数据湖与数仓的创新之路 在数字金融时代,数据已成为金融机构的核心竞争力。杭银消费金…...