【Linux系统化学习】线程概念

2024-03-03 23:52

本文主要是介绍【Linux系统化学习】线程概念,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

线程的概念

线程的引出

什么是线程

理解线程比进程更加的轻量化

线程的优点

现成的缺点

线程异常

线程用途

Linux进程VS线程

线程的简单现象


线程的概念

有关操作系统的书籍或者课本都会这样描述线程:

  • 线程是比进程轻量化的一种执行流
  • 线程是进程内部的一种执行流

线程的引出

线程的概念让我们先从之前的进程谈起

一个进程的产生,首先要将代码和数据从磁盘加载到内存中;然后创建虚拟地址空间和页表,让我们的虚拟空间和物理空间联系起来;最后操作系统给这个进程创建PCB,将PCB和虚拟地址空间建立联系,这样PCB通过虚拟地址空间和页表可以找到物理内存中可执行程序的代码。这样一系列创建进程的流程对于进程来说:地址空间是进程的资源窗口。

一个进程的出现从零到一,从无到有;需要创建PCB,申请资源空间,各种初始化,加载动态库,加载代码,各种映射;整个过程耗时耗力,成本非常高;有没有一种可能我们创建一种特殊的”进程“,只复用几经含有的进程的PCB进行创建PCB,指向这个已经含有进程的虚拟地址空间。通过各种方法把不共享的区域拆成几分,共享的保留。每个”进程“该执行自己的执行自己的,该共享的共享。将页表进行切割,实现区分。

和创建进程相比较,这个特殊的进程只需要创建一个PCB,创建非常的简单,没有各种初始化和加载,只参与进程资源的分配。非常的轻量化。在Linux操作系统中这个特殊的轻量化进程就是我们的线程。

什么是线程

  • 在一个程序里的一个执行路线就叫做线程(thread)。更准确的定义是:线程是“一个进程内部的控制序列”
  • 一切进程至少都有一个执行线程
  • 线程在进程内部运行,本质是在进程地址空间内运行
  • 在Linux系统中,在CPU眼中,看到的PCB都要比传统的进程更加轻量化
  • 透过进程虚拟地址空间,可以看到进程的大部分资源,将进程资源合理分配给每个执行流,就形成了线程执行流

因此线程的本质:

  • 线程是CPU调度的基本单位
  • 线程是承担系统资源的基本实体。

那么对于之前文章中的进程,是只含有一个执行流的进程,今天的进程含有多个执行流,每个执行流就是一个进程,也是一个线程。

理解线程比进程更加的轻量化

CPU对于一个进程的切换和一个进程的产生一样非常麻烦;需要替换页表,虚拟地址空间,代码等各种数据。而对于一个线程来说只需要替换PCB既可,线程通过对页表的切割;每个线程依然可以通过页表找到或者访问到自己的数据。其实这样的切换对于现在CPU的速度来说是可以忽略不计的。

首先我们要清楚局部性原理,对于CPU来说目前我们正在处理第10行代码有很大的概率接下来会处理第11行及以下的代码。根据冯诺依曼体系结构和木桶原理,CPU再对第11行代码进行处理的时候势必要从内存中重新加载代码。因此我们可以在CPU中添加一个缓存(cache),根据局部性原理,将接下来有很大概率被处理的代码预加载到这个缓存中即可;保存在缓存中的数据称为热数据。那么我们在回头来看切换一个进程,还需要将这个热数据进行切换,而线程则不需要。因此线程是比进程更加的轻量化。

线程的优点

  • 创建一个新线程的代价要比创建一个新进程小得多
  • 与进程之间的切换相比,线程之间的切换需要操作系统做的工作要少很多
  • 线程占用的资源要比进程少很多
  • 能充分利用多处理器的可并行数量
  • 在等待慢速I/O操作结束的同时,程序可执行其他的计算任务
  • 计算密集型应用,为了能在多处理器系统上运行,将计算分解到多个线程中实现
  • I/O密集型应用,为了提高性能,将I/O操作重叠。线程可以同时等待不同的I/O操作。

现成的缺点

性能损失

一个很少被外部事件阻塞的计算密集型线程往往无法与共它线程共享同一个处理器。如果计算密集型线程的数量比可用的处理器多,那么可能会有较大的性能损失,这里的性能损失指的是增加了额外的同步和调度开销,而可用的资源不变。

健壮性降低

编写多线程需要更全面更深入的考虑,在一个多线程程序里,因时间分配上的细微偏差或者因共享了不该共享的变量而造成不良影响的可能性是很大的,换句话说线程之间是缺乏保护的。

缺乏访问控制

进程是访问控制的基本粒度,在一个线程中调用某些OS函数会对整个进程造成影响。

编程难度提高

编写与调试一个多线程程序比单线程程序困难得多

线程异常

  • 单个线程如果出现除零,野指针问题导致线程崩溃,进程也会随着崩溃
  • 线程是进程的执行分支,线程出异常,就类似进程出异常,进而触发信号机制,终止进程,进程终止,该进程内的所有线程也就随即退出

线程用途

  • 合理的使用多线程,能提高CPU密集型程序的执行效率
  • 合理的使用多线程,能提高IO密集型程序的用户体验(如生活中我们一边写代码一边下载开发工具,就是多线程运行的一种表现)

Linux进程VS线程

  • 进程是资源分配的基本单位
  • 线程是调度的基本单位

线程共享进程数据,但也拥有自己的一部分数据:

线程ID
一组寄存器
栈(动态运行)
errno
信号屏蔽字
调度优先级                                                                                                                                          硬件上下文(动态切换)

程的多个线程共享 同一地址空间,因此Text Segment、Data Segment都是共享的,如果定义一个函数,在各线程中都可以调用,如果定义一个全局变量,在各线程中都可以访问到,除此之外,各线程还共享以下进程资源和环境:

  • 文件描述符表
  • 每种信号的处理方式(SIG_ IGN、SIG_ DFL或者自定义的信号处理函数)
  • 当前工作目录
  • 用户id和组id

进程和线程的关系如下图:

线程的简单现象

  7 8 // 新线程9 void *ThreadRoutine(void *arg)10 {11     const char *threadname = (const char *)arg;12     while (true)              13     {14         std::cout << "I am a new thread: " << threadname << ", pid: " << getpid() << std::endl;15         sleep(1);                                                                                                                     16     }17 }18                  19 int main()20 {21     // 已经有进程了22     pthread_t tid;23     pthread_create(&tid, nullptr, ThreadRoutine, (void *)"thread 1");24                    25                   26                                                                      27     // 主线程28     while (true)29     {30         std::cout << "I am main thread"31                   << ", pid: " << getpid()  << std::endl;32         sleep(1);33     }                                  34     return 0;}

上面的代码我们在主线程中创建了一个线程,两个线程含有相同的PID;而主线程的PID和LWP是一样的;LWP(Light Weight Process)译为轻量级进程的意思。


今天对Linux下线程的概念的分享到这就结束了,希望大家读完后有很大的收获,也可以在评论区点评文章中的内容和分享自己的看法;个人主页还有很多精彩的内容。您三连的支持就是我前进的动力,感谢大家的支持!!!

这篇关于【Linux系统化学习】线程概念的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/771339

相关文章

Linux进程CPU绑定优化与实践过程

《Linux进程CPU绑定优化与实践过程》Linux支持进程绑定至特定CPU核心,通过sched_setaffinity系统调用和taskset工具实现,优化缓存效率与上下文切换,提升多核计算性能,适... 目录1. 多核处理器及并行计算概念1.1 多核处理器架构概述1.2 并行计算的含义及重要性1.3 并

Linux线程之线程的创建、属性、回收、退出、取消方式

《Linux线程之线程的创建、属性、回收、退出、取消方式》文章总结了线程管理核心知识:线程号唯一、创建方式、属性设置(如分离状态与栈大小)、回收机制(join/detach)、退出方法(返回/pthr... 目录1. 线程号2. 线程的创建3. 线程属性4. 线程的回收5. 线程的退出6. 线程的取消7.

Linux下进程的CPU配置与线程绑定过程

《Linux下进程的CPU配置与线程绑定过程》本文介绍Linux系统中基于进程和线程的CPU配置方法,通过taskset命令和pthread库调整亲和力,将进程/线程绑定到特定CPU核心以优化资源分配... 目录1 基于进程的CPU配置1.1 对CPU亲和力的配置1.2 绑定进程到指定CPU核上运行2 基于

golang程序打包成脚本部署到Linux系统方式

《golang程序打包成脚本部署到Linux系统方式》Golang程序通过本地编译(设置GOOS为linux生成无后缀二进制文件),上传至Linux服务器后赋权执行,使用nohup命令实现后台运行,完... 目录本地编译golang程序上传Golang二进制文件到linux服务器总结本地编译Golang程序

Linux下删除乱码文件和目录的实现方式

《Linux下删除乱码文件和目录的实现方式》:本文主要介绍Linux下删除乱码文件和目录的实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux下删除乱码文件和目录方法1方法2总结Linux下删除乱码文件和目录方法1使用ls -i命令找到文件或目录

Linux在线解压jar包的实现方式

《Linux在线解压jar包的实现方式》:本文主要介绍Linux在线解压jar包的实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux在线解压jar包解压 jar包的步骤总结Linux在线解压jar包在 Centos 中解压 jar 包可以使用 u

linux解压缩 xxx.jar文件进行内部操作过程

《linux解压缩xxx.jar文件进行内部操作过程》:本文主要介绍linux解压缩xxx.jar文件进行内部操作,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、解压文件二、压缩文件总结一、解压文件1、把 xxx.jar 文件放在服务器上,并进入当前目录#

Linux系统性能检测命令详解

《Linux系统性能检测命令详解》本文介绍了Linux系统常用的监控命令(如top、vmstat、iostat、htop等)及其参数功能,涵盖进程状态、内存使用、磁盘I/O、系统负载等多维度资源监控,... 目录toppsuptimevmstatIOStatiotopslabtophtopdstatnmon

Javaee多线程之进程和线程之间的区别和联系(最新整理)

《Javaee多线程之进程和线程之间的区别和联系(最新整理)》进程是资源分配单位,线程是调度执行单位,共享资源更高效,创建线程五种方式:继承Thread、Runnable接口、匿名类、lambda,r... 目录进程和线程进程线程进程和线程的区别创建线程的五种写法继承Thread,重写run实现Runnab

SpringBoot线程池配置使用示例详解

《SpringBoot线程池配置使用示例详解》SpringBoot集成@Async注解,支持线程池参数配置(核心数、队列容量、拒绝策略等)及生命周期管理,结合监控与任务装饰器,提升异步处理效率与系统... 目录一、核心特性二、添加依赖三、参数详解四、配置线程池五、应用实践代码说明拒绝策略(Rejected