当前位置: 首页 > 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…...

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

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

基于算法竞赛的c++编程(28)结构体的进阶应用

结构体的嵌套与复杂数据组织 在C中,结构体可以嵌套使用,形成更复杂的数据结构。例如,可以通过嵌套结构体描述多层级数据关系: struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...

JavaScript 中的 ES|QL:利用 Apache Arrow 工具

作者:来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗?了解下一期 Elasticsearch Engineer 培训的时间吧! Elasticsearch 拥有众多新功能,助你为自己…...

【项目实战】通过多模态+LangGraph实现PPT生成助手

PPT自动生成系统 基于LangGraph的PPT自动生成系统,可以将Markdown文档自动转换为PPT演示文稿。 功能特点 Markdown解析:自动解析Markdown文档结构PPT模板分析:分析PPT模板的布局和风格智能布局决策:匹配内容与合适的PPT布局自动…...

MySQL中【正则表达式】用法

MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现(两者等价),用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例: 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...

什么是Ansible Jinja2

理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具,可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板,允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板,并通…...

AspectJ 在 Android 中的完整使用指南

一、环境配置(Gradle 7.0 适配) 1. 项目级 build.gradle // 注意:沪江插件已停更,推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...

tomcat指定使用的jdk版本

说明 有时候需要对tomcat配置指定的jdk版本号,此时,我们可以通过以下方式进行配置 设置方式 找到tomcat的bin目录中的setclasspath.bat。如果是linux系统则是setclasspath.sh set JAVA_HOMEC:\Program Files\Java\jdk8 set JRE_HOMEC:\Program Files…...

Vue 模板语句的数据来源

&#x1f9e9; Vue 模板语句的数据来源&#xff1a;全方位解析 Vue 模板&#xff08;<template> 部分&#xff09;中的表达式、指令绑定&#xff08;如 v-bind, v-on&#xff09;和插值&#xff08;{{ }}&#xff09;都在一个特定的作用域内求值。这个作用域由当前 组件…...

沙箱虚拟化技术虚拟机容器之间的关系详解

问题 沙箱、虚拟化、容器三者分开一一介绍的话我知道他们各自都是什么东西&#xff0c;但是如果把三者放在一起&#xff0c;它们之间到底什么关系&#xff1f;又有什么联系呢&#xff1f;我不是很明白&#xff01;&#xff01;&#xff01; 就比如说&#xff1a; 沙箱&#…...

ArcGIS Pro+ArcGIS给你的地图加上北回归线!

今天来看ArcGIS Pro和ArcGIS中如何给制作的中国地图或者其他大范围地图加上北回归线。 我们将在ArcGIS Pro和ArcGIS中一同介绍。 1 ArcGIS Pro中设置北回归线 1、在ArcGIS Pro中初步设置好经纬格网等&#xff0c;设置经线、纬线都以10间隔显示。 2、需要插入背会归线&#xf…...