Linux:线程的概念

个人主页 : 个人主页
个人专栏 : 《数据结构》 《C语言》《C++》《Linux》
文章目录
- 前言
- 一、线程的概念
- 线程代码的简单示例
- 总结
前言
本文是对于线程概念的知识总结
一、线程的概念
在课本上,线程是比进程更轻量级的一种指向流 或 线程是在进程内部执行的一种执行流。
我们再提出两个理解,线程是CPU调度的基本单位 / 进程是承担系统资源的基本实体。
先记住上面的结论
我们知道,进程 = 内核数据结构 + 代码和数据构成的。

CPU要调度进程,就要有运行队列,而运行队列中排队的就是pcb。CPU通过这些pcb,找到对应的地址空间,进而通过地址空间中的虚拟地址,在页表中映射物理地址,从而找到对应的代码和数据。那么,我们是不是可以将地址空间理解为进程的资源窗口,毕竟进程想要访问正文代码,数据,new和malloc的空间,共享库,栈上的临时数据,命令行参数和环境变量等都是通过地址空间来进行的。
那么,我们如果要创建进程,就要创建对应的pcb,地址空间,将磁盘中的代码和数据加载进内存,再将地址空间中的虚拟地址与物理地址映射构成页表,打开stdin,stdout,stderr构建文件资源描述表,初始化信号处理过程等,这样看来进程创建的成本还挺高的。那为了减少成本,我们能不能在进程内部,再创建多个pcb指向该进程的地址空间,将代码分成多个,并将私有的数据,使每个pcb各自私有一份,可以共享的数据就共享。当CPU来调度其中一个pcb时,其只会运行该进程的一部分代码和一部分数据。我们就可以将这种比以往进程更轻(创建成本)的东西,称为线程。

在linux程序员看来,描述线程的结构体(TCB Thread control block ) 中属性在pcb中都有。那如果我们把pcb来充当tcb,我们就可以把进程调度,切换的代码在线程级别复用起来,而不用再单独设计线程。也就说,以后再创建线程,只需要创建pcb,然后指向同一个进程地址空间,线程的管理就可以复用进程的管理代码。这就是linux中线程的实现方案。
那就有一个问题,在CPU看来,一个pcb到底是进程还是线程,或者说CPU要不要区分一个pcb是进程还是线程。答案很明显,CPU不需要区分进程和线程,CPU只需要根据pcb的地址空间来执行代码即可。也就是现在CPU拿到一个pcb,其执行流是小于等于进程的(当该进程内有多个pcb,其执行流小于进程;当该进程只有一个pcb,其执行流等于该进程)。那现在什么是进程?进程 = 该进程的所有pcb + 地址空间 + 页表 + 代码和数据。与以往进程的区别就是,现在进程内部有多个执行流,以前进程内部只有一个执行流。

红色框内的所有东西之和就是进程。
现在我们就可以理解进程是承担分配系统资源的基本实体,线程是参与资源分配。进程创建要申请系统资源,来创建一个pcb,地址空间,页表,代码和数据,线程创建就是创建一个pcb来分配该进程内部的资源(划分地址空间)。实际上,在linux中并没有真正意义的线程,只是用进程的数据结构来模拟的线程。这种描述执行流的pcb就是轻量级进程(LWP light wigth process 执行流小于等于进程)。那以后,CPU调度就不再是进程,而是一个一个的轻量级进程(pcb),也就是线程是CPU调度的基本单位。
线程比进程更轻量化的原因
- 线程创建销毁更简单,线程只需创建销毁一个pcb来参与资源的分配,而进程创建销毁不仅仅只需要一个pcb
- 线程在地址空间中运行
- 线程调度更简单;在同一进程内,线程之间切换是不需要更改地址空间和页表,只需要将运行中产生的临时数据进行切换即可,也就是只需切换少量的上下文数据。但这不是主要原因,在cpu内有一个大的存储空间cache用来进行数据的缓存(热数据),cache在缓存中是以进程为单位的,那理论上,线程做切换,就不需要切换cache,着就是线程切换更简单。因为有局部性原理(如当前访问的代码附近的代码,有可能是下次要访问的代码)给预加载机制,提供理论基础,

线程代码的简单示例
经过上面的描述,我们已经对线程有了一定的理解,下面就让我们在代码层面上来看看。
#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <sys/types.h>// 新线程
void *ThreadRountine(void *arg)
{const char *threadname = (const char *)arg;while (true){std::cout << "I am a new thread: " << threadname << ", pid: " << getpid() << std::endl;sleep(1);}
}int main()
{pthread_t tid;pthread_create(&tid, nullptr, ThreadRountine, (void*)"thread 1");// 主线程while (true){std::cout << "I am main thread" << ", pid: " << getpid() <<std::endl;sleep(1);}return 0;
}
上面代码,我们创建了一个新线程,并让主线程和新线程都执行死循环。


不出所料,只有一个进程在执行,主线程和新线程都在执行,并且pid相同(在同一个进程内)。那如何查看线程呢? ps -aL查看。

果然有两个线程,其中主线程的LWP 和 PID是相同的。在操作系统中,是通过LWP来识别不同的轻量级进程的。
#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <sys/types.h>int gnt = 100;
// 新线程
void *ThreadRountine(void *arg)
{const char *threadname = (const char *)arg;while (true){std::cout << "I am a new thread: " << threadname << ", gnt = " << gnt << ", &gnt" << &gnt << std::endl;gnt--;sleep(1);}
}int main()
{pthread_t tid;pthread_create(&tid, nullptr, ThreadRountine, (void*)"thread 1");// 主线程while (true){std::cout << "I am main thread" << ", gnt = " << gnt << ", &gnt" << &gnt <<std::endl;sleep(1);}return 0;
}
上述代码,我们创建了两个线程,其中新线程式gnt–,两个线程都打印gnt的值和地址。


可以发现两个线程共享全局变量gnt。
总结
以上就是我对于线程概念的理解和知识总结。

相关文章:
Linux:线程的概念
个人主页 : 个人主页 个人专栏 : 《数据结构》 《C语言》《C》《Linux》 文章目录 前言一、线程的概念线程代码的简单示例 总结 前言 本文是对于线程概念的知识总结 一、线程的概念 在课本上,线程是比进程更轻量级的一种指向流 或 线程是在…...
如何在jupyter notebook 中下载第三方库
在anconda 中找到: Anaconda Prompt 进入页面后的样式: 在黑色框中输入: 下载第三方库的命令 第三方库: 三种输入方式 标准保证正确 pip instsall 包名 -i 镜像源地址 pip install pip 是 Python 包管理工具,…...
Linux下du命令和df命令的使用
du命令作用是估计文件系统的磁盘已使用量,常用于查看文件或目录所占磁盘容量。df命令是统计磁盘使用情况,可以用来查看磁盘已被使用多少空间和还剩余多少空间。du命令语法du [选项] [文件或目录名称]参数:-a:--all, 列…...
AIGC笔记--条件自回归Transformer的搭建
1--概述 1. 自回归 TransFormer 规定Token只能看到自身及前面的Token,因此需生成一个符合规定的Attention Mask;(代码提供了两种方式自回归Attention Mask的定义方式); 2. 使用Cross Attention实现条件模态和输入模态之…...
数据结构->链表分类与oj(题),带你提升代码好感
✅作者简介:大家好,我是橘橙黄又青,一个想要与大家共同进步的男人😉😉 🍎个人主页:橘橙黄又青-CSDN博客 1.🍎链表的分类 前面我们学过顺序表,顺序表问题: …...
unity-unity2d基础操作笔记(三)0.5.000
目标是:牢记以下137条操作,越级上升到中级阶段 unity-unity2d基础操作笔记(三) 一百零一、如何操作一个游戏物体由多个部分组成的动画一百零二、如何使用rigidbody 2d进行物体移动一百零三、获取游戏物体身上的组件方法一百零四、代码控制物体朝向一百零五、不使用插件,纯…...
【精华】AIGC启元2024
文章目录 AIGC 前沿(1) Gemini 1.5 Pro(2) Sora(3) EMO(4) Playground v2.5(5) VSP-LLM(6) Ideogram.ai(7) LTX studio AIGC 前沿 (1) Gemini 1.5 Pro 2024.02.16 谷歌新一代多模态大模型Gemini 1.5 Pro,在性能上超越OpenAI的GPT-4 Turbo,堪称业界最强…...
js对象解构语法
对象解构语法是一种 JavaScript 的语法特性,用于从对象中提取属性,并将这些属性值赋值给变量。 基本语法 const { property1, property2 } object;object 是要解构的对象。property1 和 property2 是对象中的属性名,用花括号 {} 包裹起来表…...
flowable使用taskService.addComment新增评论需要full_msg字段进行读取
背景 在构建创业项目JeecgFlow过程中,在调用taskService.addComment接口出现了异常。就是数据存储的Message信息出现了截取,也就是存储不完整。 效果如下. flowable版本6.7.2 问题排查 接口详解及问题代码 //新增评论的接口说明 Comment addComment(…...
java常用技术栈,java面试带答案
前言 我们从一个问题引入今天的主题。 在日常业务开发中,我们可能经常听到 DBA 对我们说“不要”(注意:不是禁止)使用 join,那么为什么 DBA 对 join 这么抵触呢?是 join 本身有问题,还是我们使…...
刷题第11天
代码随想录刷题第11天 | 二叉树前中后序遍历 前序遍历 /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int x) : val(x…...
QML中动态增加表格数据
1.QML中的表格实现 import QtQuick 2.15 import QtQuick.Window 2.15import QtQuick.Controls 2.0 import Qt.labs.qmlmodels 1.0 import QtQuick.Layouts 1.15Window {width: 640height: 480visible: truetitle: qsTr("Hello World")TableModel{id:table_modelTabl…...
OBS插件开发(二)推流实时曲线
不发视频了,截个图算了,嫌麻烦 1,自定义QWidget图表绘制 ,动态更新 2,OBS直播帧率,码率监控 3,主要用于前端推流状况可视化,异常报警,及时性,无人值守直播...
Linux编程3.3 进程-进程的终止
1、正常终止 从main函数返回调用exit(标准C库函数)调用_exti或_Exit(系统调用)最后一个线程从其启动例程返回最后一个线程调用 pthread exit 2、异常终止 调用abort接受到一个信号并终止最后一个线程对取消请求做处理响应 3、进程返回 通常程序运行…...
排序(3)——直接选择排序
目录 直接选择排序 基本思想 整体思路(升序) 单趟 多趟 代码实现 特性总结 直接选择排序 基本思想 每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的…...
[LeetBook]【学习日记】数组内重组
题目:训练计划 I 训练计划 I 教练使用整数数组 actions 记录一系列核心肌群训练项目编号。为增强训练趣味性,需要将所有奇数编号训练项目调整至偶数编号训练项目之前。请将调整后的训练项目编号以数组形式返回。 示例 1: 输入:act…...
【Linux】磁盘情况、挂载,df -h无法看到的卷
文章目录 解决挂载、解决挂载完重启就消失1、查看linux下的硬盘挂载的空间、使用空间2、查看没有挂载的硬盘是否检测在系统中3、挂载 (挂载完,要在/etc/fstab 下面配置挂载信息 要不然重启挂载就消失了) 解决挂载、解决挂载完重启就消失 linu…...
AIOps实践中常见的挑战:故障根因与可观测性数据的割裂
运维的挑战与责任 在数字化时代,运维团队面临的挑战前所未有。他们不仅要确保系统的高可用性和高性能,还要快速响应并解决故障,以减少对业务的影响。在这种背景下,运维团队急需工具和技术,能够帮助他们提高效率&#…...
python 远程代码第一次推送
conda windows 环境 conda 安装后 配置环境变量 运行 conda init; conda active base 创建虚拟环境 conda create -n my_venv python3.9.5 虚拟环境应用 file-->New project --> Existing interpreter ... -->Virtualenv environment-->interpreter ...--&g…...
C++开发基础之简单的计时器也有适配场景
一、前言 计时器的开发通常涉及到计算时间间隔的方法和计算时间的方式。一般计时器的开发步骤: 获取起始时间点:在开始计时时,记录当前的时间戳作为起始时间点。 获取结束时间点:在结束计时时,记录当前的时间戳作为结…...
Appium+python自动化(十六)- ADB命令
简介 Android 调试桥(adb)是多种用途的工具,该工具可以帮助你你管理设备或模拟器 的状态。 adb ( Android Debug Bridge)是一个通用命令行工具,其允许您与模拟器实例或连接的 Android 设备进行通信。它可为各种设备操作提供便利,如安装和调试…...
8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂
蛋白质结合剂(如抗体、抑制肽)在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上,高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术,但这类方法普遍面临资源消耗巨大、研发周期冗长…...
无法与IP建立连接,未能下载VSCode服务器
如题,在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈,发现是VSCode版本自动更新惹的祸!!! 在VSCode的帮助->关于这里发现前几天VSCode自动更新了,我的版本号变成了1.100.3 才导致了远程连接出…...
可靠性+灵活性:电力载波技术在楼宇自控中的核心价值
可靠性灵活性:电力载波技术在楼宇自控中的核心价值 在智能楼宇的自动化控制中,电力载波技术(PLC)凭借其独特的优势,正成为构建高效、稳定、灵活系统的核心解决方案。它利用现有电力线路传输数据,无需额外布…...
【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表
1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...
【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)
要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况,可以通过以下几种方式模拟或触发: 1. 增加CPU负载 运行大量计算密集型任务,例如: 使用多线程循环执行复杂计算(如数学运算、加密解密等)。运行图…...
微信小程序云开发平台MySQL的连接方式
注:微信小程序云开发平台指的是腾讯云开发 先给结论:微信小程序云开发平台的MySQL,无法通过获取数据库连接信息的方式进行连接,连接只能通过云开发的SDK连接,具体要参考官方文档: 为什么? 因为…...
【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具
第2章 虚拟机性能监控,故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令:jps [options] [hostid] 功能:本地虚拟机进程显示进程ID(与ps相同),可同时显示主类&#x…...
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...
Yolov8 目标检测蒸馏学习记录
yolov8系列模型蒸馏基本流程,代码下载:这里本人提交了一个demo:djdll/Yolov8_Distillation: Yolov8轻量化_蒸馏代码实现 在轻量化模型设计中,**知识蒸馏(Knowledge Distillation)**被广泛应用,作为提升模型…...
