一、为什么要引入线程
上一篇我简单总结了一下进程的基本概念,我们已经有了进程可以用来描述运行的程序,为什么我们还要加入线程的概念?在这里,我还是通过举例子来说明。
首先,我们做一个类比,将进程看做单线程,即在某个时刻只有一个正在运行的任务。现在假设你需要使用一个字处理文件来编写一个文档,一个小时后必须提交作业到学校的作业管理系统。你打开了word文档,开始输入文字,然后花了五十分钟输入了很多文字,但是你平时没有随手按ctrl+s的好习惯,这时候当你满心欢喜地准备保存文件的时候,跳闸了,what t fuck?跳闸了!!想死的❤都有了。恢复供电后你生无可恋地打开电脑,却意外的发现百分之九十的文字还在,有没有一种死而复生的感觉。你心想这软件真好,还能帮你自动保存。好,废话就说到这。
你没有手动保存文件却只是丢失了一部分文字,这背后其实就是线程的功劳啦:编写文字作为一个线程,每个若干分钟自动保存文档是另外一个线程,两个线程同时存在于一个进程并且可以并行执行。当然,这只是线程其中一个优点。
二、什么是线程
线程是进程的一部分,用来描述指令流的执行状态,它是进程中指令执行流的最小单元,是CPU调度的最小单位。
一个进程中可以存在多个线程,它们共享该进程所拥有的地址空间和数据等资源,各个线程之间可以并发执行。
三、线程的优缺点
线程的优缺点,是在和进程对比的情况下得出的。
所以,我们讲线程的优缺点先讲进程和线程的联系和区别。
- 进程是资源分配的最小单位,线程是CPU调度的最小单位
- 进程拥有一个完整的资源平台,而线程只独享指令流执行的必要资源。比如拥有程序计数器,用来记录接着要执行哪一条指令;拥有寄存器,用来存放线程当前的工作变量;拥有堆栈,用来记录执行历史。
- 线程具有就绪、等待和运行三种基本状态和状态间的转换关系。和进程基本一致
- 进程的内存空间是天然独立的,线程的内存空间是天然共享的
线程的优缺点
同一进程的各线程间共享内存和文件资源,可不通过内核进行直接通信,所以能减少并发执行的时间和空间开销。具体表现为:
- 线程的创建和销毁时间比进程短
- 同一进程内的线程切换时间比进程短
也是因为同一进程的各线程间共享内存和文件资源,但没有独立的地址空间,所以线程存在的缺点为: 一个线程崩溃,会导致其所属进程的所有线程崩溃,健壮性不及线程
四、线程的三种实现方式
- 用户线程:在用户空间实现
- 内核线程:在内核中实现
- 轻量级线程:在内核中实现,支持用户线程
用户线程,指的是由一组用户级的线程库函数来完成线程的管理,包括线程的创建、终止、同步和调度等。从下图可见,每个进程有私有的线程控制块列表TCB,而TCB由线程函数库维护。由于它不依赖于操作系统的内核,所以在同一进程内的用户线程切换速度快,允许每个进程拥有自己的线程调度算法。相反,当线程发起系统调用而阻塞时,则整个进程进入等待,此外,这种方式只能按进程分配CPU时间,多个线程进程中,每个线程的时间片较少。
内核线程,指的是在内核通过系统调用实现的线程机制,由内核实现线程的创建、终止和管理。从下图可见,PCB和TCB由内核维护,所以线程执行系统调用而被阻塞不影响其他线程,但是线程的创建、终止和切换开销比较大。此外,这种以线程为单位进行CPU时间分配,所以多线程的进程可获得更多的CPU时间片。
轻量级线程,指的是在内核内支持用户线程,一个进程可以有一个或者多个轻量级进程,每个轻量级进程由一个单独的内核线程来支持。