当前位置: 首页 > news >正文

Linux C/C++编程中的多线程编程基本概念

【图书推荐】《Linux C与C++一线开发实践(第2版)》_linux c与c++一线开发实践pdf-CSDN博客
《Linux C与C++一线开发实践(第2版)(Linux技术丛书)》(朱文伟,李建英)【摘要 书评 试读】- 京东图书 (jd.com)

8.2.1  操作系统和多线程

要在应用程序中实现多线程,必须有操作系统的支持。Linux 32位或64位操作系统对应用程序提供了多线程的支持,所以Windows NT/2000/XP/7/8/10是多线程操作系统。根据进程与线程的支持情况,可以把操作系统大致分为如下几类:

(1)单进程、单线程,MS-DOS大致是这种操作系统。

(2)多进程、单线程,多数UNIX(及类UNIX的Linux)是这种操作系统。

(3)多进程、多线程,Win32(Windows NT/2000/XP/7/8/10等)、Solaris 2.x和OS/2都是这种操作系统。

(4)单进程、多线程,VxWorks是这种操作系统。

具体到Linux C++的开发环境,它提供了一套POSIX API函数来管理线程,用户既可以直接使用这些POSIX API函数,也可以使用C++自带的线程类。作为一名Linux C++开发者,这两者都应该会使用,因为在Linux C++程序中,这两种方式都有可能出现。

8.2.2  线程的基本概念

现代操作系统大多支持多线程概念,每个进程中至少有一个线程,所以即使没有使用多线程编程技术,进程也含有一个主线程,所以也可以说,CPU中执行的是线程,线程是程序的最小执行单位,是操作系统分配CPU时间的最小实体。一个进程的执行说到底是从主线程开始的,如果需要,可以在程序任何地方开辟新的线程,其他线程都是由主线程创建的。一个进程正在运行,也可以说是一个进程中的某个线程正在运行。一个进程的所有线程共享该进程的公共资源,比如虚拟地址空间、全局变量等。每个线程也可以拥有自己私有的资源,如堆栈、在堆栈中定义的静态变量和动态变量、CPU寄存器的状态等。

线程总是在某个进程环境中创建的,并且会在这个进程内部销毁。线程和进程的关系是:线程是属于进程的,线程运行在进程空间内,同一进程所产生的线程共享同一内存空间,当进程退出时,该进程所产生的线程都会被强制退出并清除。线程可与属于同一进程的其他线程共享进程所拥有的全部资源,但是其本身基本上不拥有系统资源,只拥有一点在运行中必不可少的信息(如程序计数器、一组寄存器和线程栈,线程栈用于维护线程在执行代码时需要的所有函数参数和局部变量)。

相对于进程来说,线程所占用的资源更少。比如创建进程,系统要为它分配很大的私有空间,占用的资源较多;而对于多线程程序来说,由于多个线程共享一个进程地址空间,因此占用的资源较少。此外,进程间切换时,需要交换整个地址空间,而线程间切换时,只是切换线程的上下文环境,因此效率更高。在操作系统中引入线程带来的主要好处是:

(1)在进程内创建、终止线程比创建、终止进程要快。

(2)同一进程内线程间的切换比进程间的切换要快,尤其是用户级线程间的切换。

(3)每个进程具有独立的地址空间,而该进程内的所有线程共享该地址空间,因此线程的出现可以解决父子进程模型中子进程必须复制父进程地址空间的问题。

(4)线程对解决客户/服务器模型非常有效。

虽然多线程给应用开发带来了不少好处,但并不是所有情况下都要去使用多线程,要具体问题具体分析。通常在下列情况下可以考虑使用多线程:

(1)应用程序中的各任务相对独立。

(2)某些任务耗时较多。

(3)各任务有不同的优先级。

(4)一些实时系统应用。

值得注意的是,一个进程中的所有线程共享它们父进程的变量,但同时每个线程可以拥有自己的变量。

8.2.3  线程的状态

一个线程在从创建到结束这一生命周期中,总是处于下面4个状态中的一个。

1)就绪态

线程能够运行的条件已经满足,只是在等待处理器(处理器要根据调度策略来把就绪态的线程调度到处理器中运行)。处于就绪态的原因可能是线程刚刚被创建(刚创建的线程不一定马上运行,一般先处于就绪态),也可能是刚刚从阻塞状态中恢复,还可能是因被其他线程抢占而处于就绪态。

2)运行态

运行态表示线程正在处理器中运行,正占用着处理器。

3)阻塞态

由于在等待处理器之外的其他条件而无法运行的状态叫作阻塞态。这里的其他条件包括I/O操作、互斥锁的释放、条件变量的改变等。

4)终止态

终止态就是线程的线程函数运行结束或被其他线程取消后处于的状态。处于终止态的线程虽然已经结束了,但它所占资源还没有被回收,而且还可以被重新复活。我们不应该长时间让线程处于这种状态,线程处于终止态后应该及时进行资源回收,下面会讲到如何回收。

8.2.4  线程函数

线程函数就是线程创建后进入运行态后要执行的函数。执行线程说到底就是执行线程函数。这个函数是我们自定义的,然后在创建线程时把我们的函数作为参数传入线程创建函数。

同理,中断线程的执行就是中断线程函数的执行,以后再恢复线程的时候,就会在前面线程函数暂停的地方继续执行下面的代码。结束线程也就不再运行线程函数。线程的函数可以是一个全局函数或类的静态函数,比如在POSIX线程库中,它通常这样声明:

void *ThreadProc (void *arg)

其中,参数arg指向要传给线程的数据,这个参数是在创建线程的时候作为参数传入线程创建函数中的。函数的返回值应该表示线程函数运行的结果:成功还是失败。注意函数名ThreadProc可以是自定义的函数名,这个函数是用户自己先定义好,然后由系统来调用。

8.2.5  线程标识

既然句柄是用来标识线程对象的,那线程本身用什么来标识呢?在创建线程的时候,系统会为线程分配唯一的ID作为线程的标识,这个ID从线程创建开始就存在,一直伴随着线程的结束才消失。线程结束后,该ID就自动不存在,我们不需要去显式清除它。

通常线程创建成功后会返回一个线程ID。

8.2.6  C++多线程开发的两种方式

在Linux C++开发环境中,通常有两种方式来开发多线程程序:一种是利用POSIX多线程API函数来开发多线程程序,另一种是利用C++自带线程类来开发多线程程序。这两种方式各有利弊。前一种方法比较传统,后一种方法比较新,是C++11推出的方法。为何C++程序员也要熟悉POSIX多线程开发呢?这是因为C++11以前,在C++里面使用多线程一般都是利用POSIX多线程API,或者把POSIX多线程API封装成类,再在公司内部供大家使用。因此,一些老项目都是和POSIX多线程库相关的,这也使得我们必须熟悉它,因为很可能进入公司后会要求维护以前的程序代码。而C++自带线程类很可能在以后开发新的项目时会用到。总之,技多不压身。

相关文章:

Linux C/C++编程中的多线程编程基本概念

【图书推荐】《Linux C与C一线开发实践(第2版)》_linux c与c一线开发实践pdf-CSDN博客《Linux C与C一线开发实践(第2版)(Linux技术丛书)》(朱文伟,李建英)【摘要 书评 试读】- 京东图书 (jd.com…...

解决Tomcat运行时错误:“Address localhost:1099 is already in use”

目录 背景: 过程: 报错的原因: 解决的方法: 总结: 直接结束Java.exe进程: 使用neststat -aon | findstr 1099 命令: 选择建议: 背景: 准备运行Tomcat服务器调试项目时,程序下…...

C/C++中的调用约定

在C/C编程中,调用约定(calling conventions)是一组指定如何调用函数的规则。主要在你调用代码之外的函数(例如OS API,操作系统应用程序接口)或OS调用你(如WinMain的情况)时起作用。如果编译器不知道正确的调用约定,那么你很可能会遇到非常奇怪…...

微信创建小程序码 - 数量不受限制

获取小程序码:小程序码为圆图,且不受数量限制。 目录 文档 接口地址 请求方式 功能描述 注意事项 获取 scene 值 请求参数 返回参数 对接 请求方法 获取小程序码 调用获取小程序码 总结 文档 接口地址 https://api.weixin.qq.com/wxa/get…...

springboot/ssm美食分享系统Java代码web项目美食烹饪笔记分享交流

springboot/ssm美食分享系统ava美食烹饪笔记分享交流系统web美食源码 基于springboot(可改ssm)vue项目 开发语言:Java 框架:springboot/可改ssm vue JDK版本:JDK1.8(或11) 服务器:tomcat 数据库&#…...

【Redis篇】 List 列表

在 Redis 中,List 是一种非常常见的数据类型,用于表示一个有序的字符串集合。与传统的链表结构类似,Redis 的 List 支持在两端进行高效的插入和删除操作,因此非常适合实现队列(Queue)和栈(Stack…...

多级IIR滤波效果(BIQUAD),system verilog验证

MATLAB生成IIR系数 采用率1k,截止频率30hz,Matlab生成6阶对应的biquad3级系数 Verilog测试代码 // fs1khz,fc30hz initial beginreal Sig_Orig, Noise_white, Mix_sig;real fs 1000;Int T 1; //周期int N T*fs; //1s的采样点数// 数组声明…...

【WPF中ControlTemplate 与 DataTemplate之间的区别?】

前言 WPF中ControlTemplate 与 DataTemplate之间的区别? 1. 定义: ControlTemplate 是用于定义 WPF 控件的外观和结构的模板。它允许您重新定义控件的视觉表现,而不改变控件的行为。 DataTemplate 是用于定义如何呈现数据对象的模板。它通…...

Keil5配色方案修改为类似VSCode配色

1. 为什么修改Keil5配色方案 视觉习惯:如果你已经习惯了VSCode的配色方案,尤其是在使用ESP-IDF开发ESP32时,Keil5的默认配色可能会让你感到不习惯。减少视觉疲劳:Keil5的默认背景可能过于明亮,长时间使用可能会导致视…...

ndp协议简介

在IPv6中,ARP(地址解析协议)被替代为邻居发现协议(Neighbor Discovery Protocol,NDP)。NDP是IPv6网络中用于发现邻居节点(相邻设备)的协议,类似于IPv4中的ARP。但与ARP不…...

stable diffusion实践操作-大模型介绍:SD的发展历史,SD1.5和SDXL之间的差别

大家有没有这样的困惑:在找模型时,老是会出现一些奇怪的标签,像 sd1.5、sdxl 之类的模型后缀,真让人摸不着头脑,一会儿 1.0,一会儿 1.5,一会儿 XL,完全搞不清楚状况。今天就来给大家…...

系统无法运行提示:sqlsut.dll初始化错误怎么解决?多种解决方法汇总一览

遇到 sqlsut.dll 初始化错误,这通常意味着 SQL Server 的某些组件未能正确加载或初始化。以下是一些可能的解决方法汇总,旨在帮助您排查和解决问题: 解决方法 1. 检查SQL Server服务状态•确认所有相关的SQL Server服务(如SQL Se…...

通过waitress启动flask应用

假设你有一个名为 app.py 的文件,app 是指你的 Flask 应用实例。并且在这个文件中创建了一个 Flask 应用实例,那么你可以这样导入和使用它。 示例结构 假设你的项目结构如下: my_flask_app/ │ ├── app.py ├── waitress_server.py └─…...

Redis高阶之容错切换

当一台主机master宕掉之后,他的从机会取代主机么? 查看集群状态 127.0.0.1:6385> cluster nodes c8ff33e8da5fd8ef821c65974dda304d2e3327f9 192.168.58.129:638216382 slave f6b1fd5e58df90782f602b484c2011d52fc3482d 0 1733220836918 1 connecte…...

蓝桥杯准备训练(lesson2 ,c++)

3.1 字符型 char //character的缩写在键盘上可以敲出各种字符,如: a , q , , # 等,这些符号都被称为字符,字符是⽤单引号括 起来的,如: ‘a’ , ‘b’ &…...

【力扣】2094.找出3为偶数

思路 方法一:使用Set集合 1.首先是三层for循环,遍历,并且遇到不满足的情况,便跳过,继续计算。不如前导为0,以及遍历同一个数组下标的情况 2.使用Set集合来确保答案是唯一的,使用桶来标记也是可以的 3.但是…...

利用红黑树封装map,和set,实现主要功能

如果不知道红黑树是什么的时候可以去看看这个红黑树 思路 首先我们可以把封装分为两个层面理解,上层代码就是set,和map,底层就是红黑树 就相当于根据红黑树上面套了两个map,set的壳子,像下面这张图一样 对于map和set,map里面存…...

网络(TCP)

目录 TCP socket API 详解 套接字有哪些类型?socket有哪些类型? 图解TCP四次握手断开连接 图解TCP数据报结构以及三次握手(非常详细) socket缓冲区以及阻塞模式详解 再谈UDP和TCP bind(): 我们的程序中对myaddr参数是这样…...

CSS 选择器的优先级

一、基本概念 CSS 选择器的优先级决定了在样式冲突时,哪个样式规则将被应用到 HTML 元素上。通过理解 CSS 选择器的优先级,可以更好地控制网页元素的样式,避免样式冲突。 二、优先级计算规则 1. 内联样式 内联样式具有最高的优先级。 &l…...

留学生数学辅导作业随机过程高等线性代数概率论微积分优化统计

针对留学生数学辅导作业中的随机过程、高等线性代数、概率论、微积分、优化以及统计等科目,以下是一些详细的辅导建议和资源概述: 一、随机过程 概念理解: 随机过程是研究随机现象随时间演变的数学分支。它涉及概率论和数理统计的知识&#…...

Flask RESTful 示例

目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题: 下面创建一个简单的Flask RESTful API示例。首先,我们需要创建环境,安装必要的依赖,然后…...

TDengine 快速体验(Docker 镜像方式)

简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能,本节首先介绍如何通过 Docker 快速体验 TDengine,然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker,请使用 安装包的方式快…...

python打卡day49

知识点回顾: 通道注意力模块复习空间注意力模块CBAM的定义 作业:尝试对今天的模型检查参数数目,并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...

大型活动交通拥堵治理的视觉算法应用

大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动(如演唱会、马拉松赛事、高考中考等)期间,城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例,暖城商圈曾因观众集中离场导致周边…...

无法与IP建立连接,未能下载VSCode服务器

如题,在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈,发现是VSCode版本自动更新惹的祸!!! 在VSCode的帮助->关于这里发现前几天VSCode自动更新了,我的版本号变成了1.100.3 才导致了远程连接出…...

FastAPI 教程:从入门到实践

FastAPI 是一个现代、快速(高性能)的 Web 框架,用于构建 API,支持 Python 3.6。它基于标准 Python 类型提示,易于学习且功能强大。以下是一个完整的 FastAPI 入门教程,涵盖从环境搭建到创建并运行一个简单的…...

页面渲染流程与性能优化

页面渲染流程与性能优化详解(完整版) 一、现代浏览器渲染流程(详细说明) 1. 构建DOM树 浏览器接收到HTML文档后,会逐步解析并构建DOM(Document Object Model)树。具体过程如下: (…...

第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明

AI 领域的快速发展正在催生一个新时代,智能代理(agents)不再是孤立的个体,而是能够像一个数字团队一样协作。然而,当前 AI 生态系统的碎片化阻碍了这一愿景的实现,导致了“AI 巴别塔问题”——不同代理之间…...

【JavaSE】绘图与事件入门学习笔记

-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角,以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向,距离坐标原点x个像素;第二个是y坐标,表示当前位置为垂直方向,距离坐标原点y个像素。 坐标体系-像素 …...

Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)

目录 一、👋🏻前言 二、😈sinx波动的基本原理 三、😈波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、🌊波动优化…...