【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 rm命令误操作的多场景防护方案与实践

《防止Linuxrm命令误操作的多场景防护方案与实践》在Linux系统中,rm命令是删除文件和目录的高效工具,但一旦误操作,如执行rm-rf/或rm-rf/*,极易导致系统数据灾难,本文针对不同场景... 目录引言理解 rm 命令及误操作风险rm 命令基础常见误操作案例防护方案使用 rm编程 别名及安全删除

Linux下MySQL数据库定时备份脚本与Crontab配置教学

《Linux下MySQL数据库定时备份脚本与Crontab配置教学》在生产环境中,数据库是核心资产之一,定期备份数据库可以有效防止意外数据丢失,本文将分享一份MySQL定时备份脚本,并讲解如何通过cr... 目录备份脚本详解脚本功能说明授权与可执行权限使用 Crontab 定时执行编辑 Crontab添加定

使用docker搭建嵌入式Linux开发环境

《使用docker搭建嵌入式Linux开发环境》本文主要介绍了使用docker搭建嵌入式Linux开发环境,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面... 目录1、前言2、安装docker3、编写容器管理脚本4、创建容器1、前言在日常开发全志、rk等不同

Java中如何正确的停掉线程

《Java中如何正确的停掉线程》Java通过interrupt()通知线程停止而非强制,确保线程自主处理中断,避免数据损坏,线程池的shutdown()等待任务完成,shutdownNow()强制中断... 目录为什么不强制停止为什么 Java 不提供强制停止线程的能力呢?如何用interrupt停止线程s

redis-sentinel基础概念及部署流程

《redis-sentinel基础概念及部署流程》RedisSentinel是Redis的高可用解决方案,通过监控主从节点、自动故障转移、通知机制及配置提供,实现集群故障恢复与服务持续可用,核心组件包... 目录一. 引言二. 核心功能三. 核心组件四. 故障转移流程五. 服务部署六. sentinel部署

linux系统上安装JDK8全过程

《linux系统上安装JDK8全过程》文章介绍安装JDK的必要性及Linux下JDK8的安装步骤,包括卸载旧版本、下载解压、配置环境变量等,强调开发需JDK,运行可选JRE,现JDK已集成JRE... 目录为什么要安装jdk?1.查看linux系统是否有自带的jdk:2.下载jdk压缩包2.解压3.配置环境

Linux搭建ftp服务器的步骤

《Linux搭建ftp服务器的步骤》本文给大家分享Linux搭建ftp服务器的步骤,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录ftp搭建1:下载vsftpd工具2:下载客户端工具3:进入配置文件目录vsftpd.conf配置文件4:

python 线程池顺序执行的方法实现

《python线程池顺序执行的方法实现》在Python中,线程池默认是并发执行任务的,但若需要实现任务的顺序执行,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋... 目录方案一:强制单线程(伪顺序执行)方案二:按提交顺序获取结果方案三:任务间依赖控制方案四:队列顺序消

Linux实现查看某一端口是否开放

《Linux实现查看某一端口是否开放》文章介绍了三种检查端口6379是否开放的方法:通过lsof查看进程占用,用netstat区分TCP/UDP监听状态,以及用telnet测试远程连接可达性... 目录1、使用lsof 命令来查看端口是否开放2、使用netstat 命令来查看端口是否开放3、使用telnet

Linux系统管理与进程任务管理方式

《Linux系统管理与进程任务管理方式》本文系统讲解Linux管理核心技能,涵盖引导流程、服务控制(Systemd与GRUB2)、进程管理(前台/后台运行、工具使用)、计划任务(at/cron)及常用... 目录引言一、linux系统引导过程与服务控制1.1 系统引导的五个关键阶段1.2 GRUB2的进化优