线程概念、线程与进程的区别

Linux-线程概念、线程与进程的区别

一. 线程概念
        1.在一个程序中的一个执行路线就叫做线程。更准确的定义是:线程是一个在进程内部运行的比进程更细致的执行流。且在Linux下没有真正的线程,因为线程与进程的结构相似,所以我们拿进程来模拟线程。

        在Linux中,目前线程的实现时Native POSIX Thread Libary简称NPTL。在这种实现下, 每个用户级线程对应一个内核中的调度实体即内核级线程,也拥有自己的进程描述符(task_struct结构体)。
      在CPU的眼里,一个PCB(进程描述符)就代表一个进程,所以说, Linux下的进程都是轻量级进程。它轻量在只包含一个PCB和少量的资源。

线程概念、线程与进程的区别_第1张图片
        CPU是根据PCB来调度的,所以,一个PCB就可以看做一个执行流,所以可以将一个PCB理解为一个线程(资源忽略不计)。


        2.对于进程来说,它在创建时必有一个PCB,所以任何进程拥有至少一个执行流和资源(地址空间等)。进程拥有资源的多少是通过它的地址空间来看到的。
        在上图中,一个进程包括上述的4个PCB,虚拟地址空间,页表,物理内存等,可以将上述整张图都称为进程。而对于线程来说只有一个PCB和进程中的少量资源。所以可以说在上图所表示的进程中,共有4个PCB,所以有4个执行流,所以有4个线程。
        在CPU的眼里,一个PCB(进程描述符)就代表一个进程,所以说,Linux下的进程都是轻量级进程,它轻量在只包含一个PCB和少量的资源。

二. 线程的实现方式
        此处借鉴于博客点击打开链接

        线程有两种实现方式:用户级线程和内核级线程

1. 内核级线程
(1)定义

        在操作系统中,无论是系统进程还是用户进程,都是在操作系统内核的支持下运行的。而内核级线程也是在内核的支持下运行的。它们的创建,切换,销毁等都是在内核空间实现的。为了对内核级线程进行控制和管理,在内核空间内为每个线程设置了一个线程控制块(用PCB模拟实现),内核根据该控制块而感知该线程的存在。
(2)优点:若一个进程中的线程阻塞了,内核可以调度该进程中的其他内核级线程来运行。
(3)缺点:对于用户进程的线程来讲,它是在用户空间运行的,而内核级线程的调度和管理是在内核实现的。 所以当一个线程要切换到另一个线程时,需要从用户态进入到内核态进行,此时系统的开销较大。
2. 用户级线程
(1)定义
        用户级线程是在用户空间实现的,对于用户级线程的创建、切换、销毁等都无需内核的支持,即用户级线程是与内核无关的。可以说是内核完全不知道用户级线程的存在。对于设置了用户级线程的系统,其调度仍是以进程为单位来进行的。
(2)优点
        1)线程切换不需要转换到内核空间;
        2)调度算法可以是进程专用的;
        3)用户级线程的实现与操作系统的平台无关。
(3)缺点
        1)当一个用户级线程执行一个系统调用时,不仅该线程会阻塞,该进程中的所有线程也会被阻塞。而对于内核级线程来讲,该进程中的其他线程仍可以运行;
        2)CPU的调度是以进程为单位进行的,而对于内核级线程来讲,是以线程为单位进行调度的。

三. 线程的资源

        一个进程中的线程大部分资源是共享的,但是线程也拥有自己的一部分数据。

1. 共享资源:
(1)地址空间:由定义可知,同一进程中的所有线程都可以看到同一地址空间。比如在进程中定义一个全局变量,该进程中的所有线程都可以看到该全局变量;
(2)文件描述符表:它是以进程为单位分配的,原理与(1)一样;
(3)各种信号的处理方式;
(4)当前工作目录;
(5)用户ID和组ID


2. 私有资源:
(1)线程ID:用于唯一的标识该线程;
(2)一组寄存器(私有的上下文信息):因为线程作为调度的实体,在切换时要将当前的状态保存在寄存器中,以备将来要切换回来时使用;
(3)私有栈:用于保存临时数据(调用函数时产生的临时变量等);
(4)errno;
(5)信号屏蔽字;
(6)调度优先级。

四. 线程与进程的区别
1. 进程是承担系统资源的基本实体; 线程是调度的基本单位。
2. 进程是系统中拥有资源的一个基本单位;而线程本身并不拥有资源,只有一些必不可少的,能保证其独立运行的资源。

3.创建一个新线程的代价比创建一个新进程的代价小的多。创建一个进程需要创建PCB,地址空间,页表,分配物理内存上的数据等资源;而创建一个线程只需创建一个PCB,再给其分配少量的资源即可。
4.线程之间的切换相对于进程的切换需要操作系统做的工作少的多。比如线程之间的切换不需要切换地址空间,而进程需要。
5.销毁一个线程比销毁一个进程的代价小的多。销毁一个线程只需回收PCB和少量的资源,而销毁一个进程则需要回收该进程中的所有PCB即及其所拥有的所有资源。
6.当一个程序运行起来后,一个线程出错,该线程所属的进程(包含该进程中的其他线程)全部挂掉。系统回收进程资源。而一个进程出错,不会影响其它进程。所以说,进程更安全,线程更方便。
7.线程之间的大部分资源都是共享的。而进程之间是独立的,所以线程之间相对于进程之间对临界资源的互斥与同步操作需要的更多。

五.线程的优缺点
1. 优点

(1)创建一个线程的代价比创建一个进程要小的多;
(2)线程间的切换也比进程间的切换需要操作系统做的工作少很多;
(3)线程占用的资源比进程少的多;
(4)线程能够充分利用多处理器的可并行数量;
(5)在等待慢I/O操作结束的同时,程序可执行其他的计算任务;
(6)计算密集型应用时,为了能够在多处理器系统上运行,将计算分解到多个线程实现(不一定提高了效率);
(7)I/O密集型应用,为了提高性能,将I/O操作重叠,线程可以同时等待不同的I/O操作。

2. 缺点
(1)性能损失:若计算密集型线程的数量比可用的处理器多,会增加额外的同步和调度开销,但是可用资源不变;
(2)健壮性降低:因为线程共享同一个地址空间,若是一个线程出现问题,整个进程会出错;
(3)缺乏访问控制:若是有两个或多个线程同时对同一个数据进行修改,那每个线程看到的都是不同的数据,我们不知道哪个数据才是正确的;
(4)编程难度提高:编写一个多线程程序比一个单线程程序要难的多,因为为了防止(3)中的情况,我们要对线程进行加锁、同步互斥等操作。


你可能感兴趣的:(Linux)