【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 ls命令操作详解

《Linuxls命令操作详解》通过ls命令,我们可以查看指定目录下的文件和子目录,并结合不同的选项获取详细的文件信息,如权限、大小、修改时间等,:本文主要介绍Linuxls命令详解,需要的朋友可... 目录1. 命令简介2. 命令的基本语法和用法2.1 语法格式2.2 使用示例2.2.1 列出当前目录下的文

Python 迭代器和生成器概念及场景分析

《Python迭代器和生成器概念及场景分析》yield是Python中实现惰性计算和协程的核心工具,结合send()、throw()、close()等方法,能够构建高效、灵活的数据流和控制流模型,这... 目录迭代器的介绍自定义迭代器省略的迭代器生产器的介绍yield的普通用法yield的高级用法yidle

Linux中的计划任务(crontab)使用方式

《Linux中的计划任务(crontab)使用方式》:本文主要介绍Linux中的计划任务(crontab)使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、前言1、linux的起源与发展2、什么是计划任务(crontab)二、crontab基础1、cro

Linux换行符的使用方法详解

《Linux换行符的使用方法详解》本文介绍了Linux中常用的换行符LF及其在文件中的表示,展示了如何使用sed命令替换换行符,并列举了与换行符处理相关的Linux命令,通过代码讲解的非常详细,需要的... 目录简介检测文件中的换行符使用 cat -A 查看换行符使用 od -c 检查字符换行符格式转换将

Linux系统配置NAT网络模式的详细步骤(附图文)

《Linux系统配置NAT网络模式的详细步骤(附图文)》本文详细指导如何在VMware环境下配置NAT网络模式,包括设置主机和虚拟机的IP地址、网关,以及针对Linux和Windows系统的具体步骤,... 目录一、配置NAT网络模式二、设置虚拟机交换机网关2.1 打开虚拟机2.2 管理员授权2.3 设置子

Linux系统中卸载与安装JDK的详细教程

《Linux系统中卸载与安装JDK的详细教程》本文详细介绍了如何在Linux系统中通过Xshell和Xftp工具连接与传输文件,然后进行JDK的安装与卸载,安装步骤包括连接Linux、传输JDK安装包... 目录1、卸载1.1 linux删除自带的JDK1.2 Linux上卸载自己安装的JDK2、安装2.1

Linux卸载自带jdk并安装新jdk版本的图文教程

《Linux卸载自带jdk并安装新jdk版本的图文教程》在Linux系统中,有时需要卸载预装的OpenJDK并安装特定版本的JDK,例如JDK1.8,所以本文给大家详细介绍了Linux卸载自带jdk并... 目录Ⅰ、卸载自带jdkⅡ、安装新版jdkⅠ、卸载自带jdk1、输入命令查看旧jdkrpm -qa

Linux samba共享慢的原因及解决方案

《Linuxsamba共享慢的原因及解决方案》:本文主要介绍Linuxsamba共享慢的原因及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux samba共享慢原因及解决问题表现原因解决办法总结Linandroidux samba共享慢原因及解决

Spring Boot3虚拟线程的使用步骤详解

《SpringBoot3虚拟线程的使用步骤详解》虚拟线程是Java19中引入的一个新特性,旨在通过简化线程管理来提升应用程序的并发性能,:本文主要介绍SpringBoot3虚拟线程的使用步骤,... 目录问题根源分析解决方案验证验证实验实验1:未启用keep-alive实验2:启用keep-alive扩展建

新特性抢先看! Ubuntu 25.04 Beta 发布:Linux 6.14 内核

《新特性抢先看!Ubuntu25.04Beta发布:Linux6.14内核》Canonical公司近日发布了Ubuntu25.04Beta版,这一版本被赋予了一个活泼的代号——“Plu... Canonical 昨日(3 月 27 日)放出了 Beta 版 Ubuntu 25.04 系统镜像,代号“Pluc