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++开发基础之简单的计时器也有适配场景
一、前言 计时器的开发通常涉及到计算时间间隔的方法和计算时间的方式。一般计时器的开发步骤: 获取起始时间点:在开始计时时,记录当前的时间戳作为起始时间点。 获取结束时间点:在结束计时时,记录当前的时间戳作为结…...

智能在线客服平台:数字化时代企业连接用户的 AI 中枢
随着互联网技术的飞速发展,消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁,不仅优化了客户体验,还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用,并…...

苍穹外卖--缓存菜品
1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得,如果用户端访问量比较大,数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据,减少数据库查询操作。 缓存逻辑分析: ①每个分类下的菜品保持一份缓存数据…...

微服务商城-商品微服务
数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...

算法笔记2
1.字符串拼接最好用StringBuilder,不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>()); 3.去掉首尾空格...

2025季度云服务器排行榜
在全球云服务器市场,各厂商的排名和地位并非一成不变,而是由其独特的优势、战略布局和市场适应性共同决定的。以下是根据2025年市场趋势,对主要云服务器厂商在排行榜中占据重要位置的原因和优势进行深度分析: 一、全球“三巨头”…...

【Linux】Linux 系统默认的目录及作用说明
博主介绍:✌全网粉丝23W,CSDN博客专家、Java领域优质创作者,掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围:SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物…...
Kubernetes 网络模型深度解析:Pod IP 与 Service 的负载均衡机制,Service到底是什么?
Pod IP 的本质与特性 Pod IP 的定位 纯端点地址:Pod IP 是分配给 Pod 网络命名空间的真实 IP 地址(如 10.244.1.2)无特殊名称:在 Kubernetes 中,它通常被称为 “Pod IP” 或 “容器 IP”生命周期:与 Pod …...
WEB3全栈开发——面试专业技能点P4数据库
一、mysql2 原生驱动及其连接机制 概念介绍 mysql2 是 Node.js 环境中广泛使用的 MySQL 客户端库,基于 mysql 库改进而来,具有更好的性能、Promise 支持、流式查询、二进制数据处理能力等。 主要特点: 支持 Promise / async-await…...

Mac flutter环境搭建
一、下载flutter sdk 制作 Android 应用 | Flutter 中文文档 - Flutter 中文开发者网站 - Flutter 1、查看mac电脑处理器选择sdk 2、解压 unzip ~/Downloads/flutter_macos_arm64_3.32.2-stable.zip \ -d ~/development/ 3、添加环境变量 命令行打开配置环境变量文件 ope…...
基于Uniapp的HarmonyOS 5.0体育应用开发攻略
一、技术架构设计 1.混合开发框架选型 (1)使用Uniapp 3.8版本支持ArkTS编译 (2)通过uni-harmony插件调用原生能力 (3)分层架构设计: graph TDA[UI层] -->|Vue语法| B(Uniapp框架)B --&g…...