【Linux】多线程:线程概念,线程与进程的区别与联系,多线程相较于多进程 ...

打印 上一主题 下一主题

主题 574|帖子 574|积分 1722

目录
一、进程基本属性回顾
二、线程概念
三、操纵系统为什么要引入线程—多进程和多线程的区别 
为什么多线程比多线程调度服从更快?
 四、线程的优点
 五、线程的缺点
六、线程非常


一、进程基本属性回顾

在学习线程之前,我们先往返顾一下进程的基本属性:
1、进程是一个可拥有资源的独立单元——即进程是系统资源分配的基本单元。一个进程可以或许独立运行,就必须拥有肯定的资源,包括:存放程序正文和数据的磁盘、内存地址空间、运行时所必要的I/O装备、进程已经打开的文件、信号量等。
2、进程是一个可独立调度和分派的基本单元。每个进程在系统中均有唯一的PCB(在Linux系统中是task_struct),系统可以根据PCB来感知进程的存在,也可以根据PCB中的信息对进程举行调度,还可将断点信息生存在进程的PCB中 。反之,也可以利用PCB中的信息来规复进程运行的现场。
正是由于进程具有以上基本属性,进程才成为了可以独立运行的基本单元,从而也构成了进程并发执行的基础。
二、线程概念

那么什么是线程呢?我们先引入如下概念:线程是进程的一个实体,是CPU调度和分派的基本单元!
到这里可能有同学会有疑问了:之前不是说进程是是一个可独立调度和分派的基本单元吗?如今怎么又说线程是CPU调度和分派的基本单元了?
   其实在已经引入线程的操纵系统中,就已经把线程作为CPU调度和分派的基本单元了!
  在Linux系统当中,我们可以这么来理解进程和线程:进程是操纵系统举行资源分配的基本单元,线程是CPU调度和分派的基本单元!
  那我们如何理解之前所学的进程呢?我们之前所学习的进程中,其实只包含一个执行流,也就是一个线程!实际上,我们之前所学习的进程是:具有一个执行流的进程,而一个进程必须至少拥有一个线程!!!
 
举个更通俗的例子:在我们国家中,家庭通常是政府举行资源分配的单元,则家庭可以视为进程,而一个家庭至少包含一个家庭成员,也可包含多个,且家庭成员共享家庭的资源,但家庭成员又有各自的隐私,因此可以将家庭成员视为线程。家庭成员各自的任务和活动(如工作、学习、娱乐)可能会差别,但都在共享的家庭资源框架内举行。这类似于线程在进程中执行差别的操纵,虽然每个线程可能执行差别的任务,但都在同一进程的资源和环境下运行。增长一个新的家庭成员(比如增长一个后代)相对容易,家庭的资源和管理模式不会发生庞大改变。这类似于创建新线程的开销很小,由于新线程与现有线程共享资源和环境。相比之下,创建一个新的家庭(即进程)必要更多的资源和管理资本。
通过上图我们可以大抵相识到:
1、在一个程序里的一个执行门路就叫做线程(thread)。更准确的定义是:线程是“一个进程内部的控制序列”。
2、线程在进程内部运行,本质是在进程地址空间内运行。线程就是进程中的一个执行单元,是进程的一部门一个进程至少有一个线程(主线程)可以创建多个线程来并行执行任务
3、透过进程假造地址空间,可以看到进程的大部门资源,将进程资源合理分配给每个执行流,就形成了线程执行流。同一进程中的所有线程共享进程的资源,但它们的执行是独立的。线程有自己的执行路径,可以同时举行多项任务,从而实现并发。
4、进程的多个线程共享同一地址空间,因此代码段和数据段都是共享的,假如定义一个函数,在各线程中都可以调用,假如定义一个全局变量,在各线程中都可以访问到,除此之外,各线程还共享以下进程资源和环境:文件形貌符表、每种信号的处理方式、当前工作目录、用户 ID 和组 ID

【相识】:但是实际上,Linux操纵系统并没直接创造“线程”这一具体的事物,而是通过创造“轻量级进程(Lightweight Process, LWP)”来实现线程的功能。
   用户视角:Linux 利用 pthread(POSIX线程)库来提供线程创建和管理的接口。pthread 库为线程提供了标准化的 API,允许程序员创建和管理线程、举行线程同步等。
  内核视角:在内核中,每个线程是一个进程,但具有某些共享资源。内核的调度器处理这些线程就像处理进程一样。
  所以我们在Linux系统中编写程序时,我们所面临的是pthread库为我们提供的管理“线程”的方法,在内核中实际上是被看成轻量级进程(LWP)来处理的,因此我们称Linux中的线程为“用户级线程”。而在Windows操纵系统中,内核为线程专门创造了TCB这一数据布局来对每个线程举行标识和管理,而这些操纵都由Windows内核来举行管理,所以我们称之为内核级线程。 
所以在Linux内核看来,对线程的调度与管理实际上就是对进程的调度与管理,依然可以沿用进程调度的那一套算法。而Windows则必要单独为线程创造一套专属的数据布局与方法。
这也是为什么在 Linux 系统中:在 CPU 眼中,看到的 PCB 都要比传统的进程更加轻量化!
三、操纵系统为什么要引入线程—多进程和多线程的区别 

实际上,线程的引入是为了更好的提高程序的并发程度。
在引入线程这一概念之前,程序的并发执行多由多进程举行实现。但是通过之前的学习我们知道:进程是系统资源分配的单元,当多个进程并发执行时,势必会为系统资源的分配带来压力!
   利用多进程时,系统必须要举行如下操纵:
  1、创建进程:系统在创建一个进程时,必须为它分配其所必须的、除处理机以外的所有资源(如内存空间、I/O装备等),并创建对应的PCB。
  2、撤销进程:系统在撤销进程时,必须先对其所占据的资源执行回收操纵,然后再撤销PCB。
  3、进程切换:对进程举行上下文切换时,必要保留当进步程的CPU环境,这一过程必要花费不少的处理机时间。
  
  由于进程是资源的拥有者,因此在对进程举行管理时,操纵系统必须付出较大的时空开销。这就限制了系统中所设置的进程的数量,而且进程的切换也不宜过于频繁,从而限制了程序并发程度的进一步提高。
  因此为使多个程序可以或许更好的并发执行,同时又能减少系统的开销,线程就应运而生。线程的出现将进程的两个基本属性分割开来:今后进程仅作为拥有资源的基本单元,线程则成为了调度和分派的单元。因此,在利用多线程时,由于多线程共享所属进程中的资源,因此减少了资源的频繁切换。
   但同时,线程也有属于自己的资源:
  

  • :每个线程都有自己的独立的栈,用于存放函数调用时执行上下文的数据,如局部变量、函数参数等。栈是线程特有的,可以确保线程之间不受其他线程的影响。
  • 一组寄存器的状态:线程执行时所利用的寄存器,例如,程序计数器、寄存器组等,每个线程都有自己的寄存器状态,这是独立于其他线程的。
  • 线程ID:每个线程都有自己的线程标识符(Thread ID),可以在同一进程中的其他线程或同级的用户程序中举行线程间通讯或同步时识别和引用。
  • 执行上下文:线程的执行上下文包含其调用的特定状态,如寄存器状态、指令指针等。这些状态在上下文切换时被生存和规复。
  • 线程局部存储(TLS):线程局部存储是特定于线程的全局变量,允许每个线程拥有一个独立的副本,但此全局变量必须为内置类型,且必要在变量类型前利用__thread关键字。
  • errno :在多线程程序中,errno 通常被实现为线程局部存储(TLS),每个线程有自己的 errno 副本,确保线程之间不会相互干扰。
  • 信号屏蔽字:每个线程都有自己的信号屏蔽字,它决定了该线程是否响应某些信号。线程可以通过系统调用(如 sigprocmask)来设置或更改信号屏蔽字。
  • 调度优先级:每个线程都有一个调度优先级,操纵系统根据这些优先级来安排线程的运行。高优先级的线程通常会比低优先级的线程获得更多的 CPU 时间。
   云云,我们便不难答复:
为什么多线程比多线程调度服从更快?

1、共享资源:多个线程可以在同一个进程中共享资源,如堆栈、状态和数据。这意味着它们可以更快地访问同样的内存地址,减少了内存的访问时间。
2、上下文切换:线程的上下文切换通常比进程的上下文切换速度更快。由于线程共享了地址空间和大部门内核资源,所以切换线程所需的时间相比于进程要短。
3、缓存命中率:在多线程应用程序中,多个线程可以共享缓存中的数据,这可以提高缓存命中率。由于多个线程共享同样的数据,这意味着他们更有可能从高速缓存中读取数据,而不是从更慢的主存中读取。
   缓存(Cache)是一种基于内存的高速数据存储技术,用于提高数据访问速度。缓存可以是硬件层面的,也可以是软件层面的。在盘算机科学中,缓存重要用在CPU缓存中,即高速缓存。
  4、减少系统调用:在多线程应用程序中,多个线程可以在同一个进程中共享相同的文件形貌符和网络毗连,这意味着它们可以重用同样的一些资源,而不是创建多个进程时必须重新打开资源。
5、减少地址空间开销:进程有它们自己的地址空间,而线程共享相同的地址空间,这意味着多个线程可以节省假造内存的开销。
 四、线程的优点

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

• 等候利用共享资源时会使程序的运行速度变慢,这些共享资源重要是独占性的资源,如打印机等。
• 对线程举行管理要求额外的CPU开销。线程的利用会给系统带来上下文切换的额外负担,当这种负担超过肯定程度时,多线程的缺点会表现得较突出,比如用独立的线程来更新数组内每个元素。
•线程的死锁。即较长时间的等待或资源竞争,以及死锁等多线程症状。
•对公有变量的同时读或写。当多个线程必要对公有变量举行写操纵时,后一个线程往往会修改掉前一个线程存放的数据,从而使前一个线程的参数被修改;另外,当公用变量的读写操纵是非原子性时,在差别的呆板上,中断时间的不确定性会导致数据在一个线程内的操纵产生错误,从而产生莫名其妙的错误,而这种错误是程序员无法预知的。
六、线程非常


  • 线程非常与进程崩溃

    • 线程在运行过程中假如发生非常,如除零错误、访问野指针等,通常会导致线程崩溃。这些非常可能会引发操纵系统层面的信号(例如 SIGFPE 对于除零错误,SIGSEGV 对于访问非法内存),这些信号会触发进程的停止机制。
    • 当一个线程崩溃时,通常会导致整个进程的崩溃。这是由于线程共享进程的地址空间和资源,线程的非常可能会粉碎进程的整体状态,从而导致进程无法继承安全地运行。

  • 信号机制

    • 当线程发生致命非常时,操纵系统会发送信号到进程,这些信号可能会导致进程的停止。例如,除零错误可能触发 SIGFPE,访问非法内存可能触发 SIGSEGV。这些信号会通知操纵系统对进程举行处理,通常会导致整个进程的退出。
    • 在某些环境下,可以利用信号处理机制来捕获这些信号,从而举行一些清理工作或记录日记,但通常环境下,假如信号表示严重错误,进程会被停止。




免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

笑看天下无敌手

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表