• 什么是线程及线程相关知识


    1.线程是什么

    通过之前的学习,我们可以了解到进程是正在执行的程序,但是进行在一个时间只能干一件事。如果向同时做两件事,进程是没有办法做到的,但是线程可以做到。

    线程就是为了让进程能够同时干多件事而发明的一种“分身术”。
    
    • 1

    由于线程是进程的分身,那么线程和进程在本质上是一样的,拥有同样的程序文本。但是线程不拥有系统资源,只有运行必须的一些数据结构。但是尽管线程是进程的分身,它们之间还是由区分的,就是线程执行时的上下文不一致。一般来说,我们说:

    线程是进程里面的一个执行上下文或者执行序列。执行序列就是一组有序指令的集合——函数。
    在线程模式下,一个进程至少有一个线程(主线程,即main方法代表的执行序列),但也可以有多个线程。也就是说,一个进程可以同时拥有多个执行序列。
    
    • 1
    • 2

    在这里插入图片描述
    进程、线程就好像一场舞台剧,舞台上可以有多个演员同时出场,这些演员和舞台就构成了一场剧。其中,每个演员就是一个线程,舞台是地址空间,这个同一个地址空间里面的所有线程就构成了进程。

    1.1线程优点

    将进程分解为线程可以有效利用多处理器和多核计算机。在没有线程的情况下,增加处理器并不能提高进程的执行效率。但如果分解为多个线程,则可以让不同的线程同时运转在不同的处理器上,提高进程的执行速度。

    2.线程的管理

    线程管理就是维护线程的各种信息,包括线程的各种关键资料。
    存放线程信息的数据结构称为线程控制表或线程控制块(TCB)。
    基于线程共享一个进程空间,线程的许多资源都是共享的。
    共享的资源存放在进程控制块(PCB)里面。不被共享的资源放在线程控制块里面。
    
    • 1
    • 2
    • 3
    • 4

    资源共享和独享就像在一个教室上课的学生,教室里面很多东西都是共享的,如投影,粉笔,话筒等;但有的东西则是每个人独享的,如座位等。
    那么如何判断那些资源为同一进程的不同线程共享,那些资源不被共享?一般的判断标准为:

    如果某资源不独享会导致线程运行错误,则该资源就由每个线程独享;而其他资源都由进程里面的所有线程所共享。
    
    • 1

    基于此,给出一般情况下,同一进程的线程间共享和独享资源的划分:

    线程共享资源线程独享资源
    地址空间程序计数器(每个线程的执行序列不一样)
    全局变量寄存器(线程的上下文)
    打开的文件栈(线程的上下文)
    子进程状态字
    闹铃
    信号及信号服务程序
    记账信息

    3.线程的实现方式(内核级线程、用户态线程和混合级线程)

    由于线程是进程的构成部分,那么线程的管理就有两种方式:①进程自己来管理线程,②操作系统来管理线程。
    基于这两种不同的选择就出现了线程实现的两种方式:①内核线程实现(操作系统来管理线程),②用户态线程实现(进程自己来管理线程)。
    
    • 1
    • 2

    思考:进程为什么不区分实现方式?
    答:进程是在CPU上实现并发,而CPU是由操作系统管理的,因此,进程的实现只能由操作系统内核来进行,而不存在用户态实现的情况。

    3.1 内核级线程

    操作系统管理线程,就要保持维护线程的各种信息,即将线程控制块存放在操作系统内核空间。这样,操作系统内核就同时拥有进程控制块和线程控制块。而根据进程控制块和线程控制块提供的信息,操作系统就可以对线程进行类似进程的管理,比如线程调度、线程的资源分配、各种安全措施的实现。

    优点

    1. 用户编程保持简单。
      因为线程的复杂性由操作系统承担,用户程序员在编程时无需管理线程的调度,即无需担心线程什么时候结束、什么时候挂起。
    2. 如果一个线程执行阻塞操作,操作系统可以从容地调度另外一个线程执行。因为操作系统的能够监控所有线程。

    缺点

    1. 效率低,因为线程在内核态实现,每次线程切换都需要陷入到内核,由操作系统进行调度。而从用户态陷入到内核态是要花时间的。
    2. 内核态占用内核稀缺的内存资源,因为操作系统需要维护线程表。操作系统所占内存空间一旦装载结束后就已经固定,无法动态改变。由于线程的数量通常大大高于进程的数量,那么随着线程数量的增加,操作系统内核空间将迅速耗尽。
    3. 内核态实现需要修改操作系统,促使了用户态线程的诞生。
      在这里插入图片描述

    3.2用户态线程

    用户态线程是用户自己做线程的切换,自己管理线程的信息,而操作系统无需知道线程的存在。
    用户态在调度线程时,必须写一个执行系统作为调度器,即除了正常执行任务的线程外,还有一个专门负责线程调度的线程。
    
    • 1
    • 2

    下面用图来展示一下用户态线程实现:
    在这里插入图片描述

    优点

    1. 灵活性高,操作系统不需要知道线程的存在,所有在任何操作系统上面都可以应用。
    2. 线程切换快,线程切换在用户态执行,无需进入内核态
    3. 不用修改操作系统,实现容易。

    缺点

    1. 程序编写困难,各线程相互合作使用CPU,程序中考虑什么时候让出CPU使用权较难

    2. 无法达到线程目标(进程级多道编程)

    3. 在执行过程中,如果一个线程阻塞,它无法将CPU控制权交出,这样整个进程无法向前推进。OS随即将CPU控制权交给另外一个进程。

      线程阻塞解决办法:
      ①在线程执行任何系统调用之前,先确认该调用是否会发生阻塞,如果会,就禁止调用;否则就放行。(前提条件是该调用在等待一段时间后一定会变为非阻塞调用)
      ②进程阻塞后,激活受阻进程的其他线程。在一个进程挂起后,OS并不立即切换到别的进程,而是该进程第二次机会,让其继续执行。如果该进程只有一个线程,或者其所有线程都已经阻塞,则控制权再次返回给OS。(修改操作系统进程切换时的指令,让其不是立即切换到别的进程;违背了层次架构原则(本应该执行系统调用操作系统);不安全)
      
      • 1
      • 2
      • 3

    3. 3 混合级线程(结合以上两种方式来实现)

    基于以上两中实现方式的优缺点,提出了一种将两者结合起来的混合级线程。
    用户态的执行系统负责进程内部线程在非阻塞时的切换。
    内核态的操作系统负责阻塞线程的切换。
    内核态线程数量较少,而用户态线程数量多。
    用户态线程被多路复用到内核态线程上,即每个内核线程可以服务一个或多个用户态线程。
    如果一个线程阻塞,则与其同一组的线程皆阻塞,但另外一组线程却可以继续执行。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在这里插入图片描述

    在分配线程时,将需要执行阻塞操作的线程设定为内核态线程,不会执行阻塞操作的线程设为用户态线程。
    
    • 1

    3.4从用户态到内核态

    线程从用户态到内核态的两种情况:
    ①在程序运行过程中发生中断或者异常,系统将自动切换到内核态运行中断或异常处理机制。
    ②程序进行系统调用也将造成用户态进入内核态。
    
    • 1
    • 2
    • 3

    总结

    线程和进程的区别

    1. 线程是CPU调度的最小单位, 进程是系统资源分配的最小单位
    2. 线程间的切换效率相比于进程间的切换要高
    3. 进程创建消耗的资源大,线程相对小一些,所以创建线程的效率也能稍微高一些
    4. 进程都是相互独立的,而一个进程内的线程共享很多资源的(地址空间)
    5. 进程间的通信就需要一些特殊的技术,线程通信就比较简单(线程就要考虑安全问题)
    6. 线程只有相关堆栈、寄存器和线程控制表TCB组成。寄存器可以存储本线程的局部变量。

    线程优缺点

    优点

    线程在进程级别实现了多道编程,使得一个进程可以同时干好多事,提高了程序运行效率,提高了硬件资源的使用率。
    
    • 1

    缺点

    ①系统运行的不确定性(单个线程的执行效率,执行准确性均存在不确定性)
    ②多线程中出现异常很麻烦
    
    • 1
    • 2
  • 相关阅读:
    添加docker容器数据卷
    笔记本键盘失灵的修复方法
    php万能表单系统源码 支持自定义+收费表单活动报名 适合多行业
    mysql -测试和优化
    java项目-第147期ssm社区生活超市管理系统_(spring+springmvc+mybatis+jsp)_java毕业设计_计算机毕业设计
    JDBC反序列化分析
    C# halcon SubImage的使用
    大端与小端:显示、存储和读取
    全波形反演培训的思考与总结
    239 滑动窗口最大值(单调队列)
  • 原文地址:https://blog.csdn.net/qq_44423388/article/details/127770831