一、线程概念
1.1 什么是线程
- 线程(thread)是进程中的一条执行路线,也可以说成线程是“一个进程内部的控制序列”。
通过下面内容可以理解“线程(thread)是进程中的一条执行路线”:
在我们之前学的进程中,一个进程的创建,操作系统会给该进程创建一个进程控制块(PCB),还要拷贝父进程的进程地址空间。如果子进程对父进程的数据进行读取并写入,就会发生写时拷贝,体现了进程的独立性。如果我们想要让该子进程能够和父进程一起去执行某个任务,则需要让子进程task_struct去指向父进程的进程地址空间,自己不需要自己的进程地址空间,这样当子进程去对父进程的数据进行写入时,就不会发生写时拷贝了,也可以和父进程一起完成任务,想当于该父进程有两个执行流,而这样的子进程可以通过vfork函数来创建。
我们有可以得出
- 一切进程至少都有一个执行线程(我们之前学的进程都是单线程进程)
如果多线程创建好了,进程中的多个线程都看见看到同一块资源,而进程对这块资源分配给线程来完成一个任务。
- 所以说线程是在进程内部完成的,本质是在进程地址空间内运行的。
- 在Linux系统中,在CPU眼中,看到的PCB都要比传统的进程更加轻量化
- 透过进程虚拟地址空间,可以看到进程的大部分资源,将进程资源合理分配给每个执行流,就形成了线程执行流
1.2 线程的优点
- 创建一个新线程的代价要比创建一个新进程小得多
- 与进程之间的切换相比,线程之间的切换需要操作系统做的工作要少很多
- 线程占用的资源要比进程少很多
- 能充分利用多处理器的可并行数量
- 在等待慢速I/O操作结束的同时,程序可执行其他的计算任务
- 计算密集型应用,为了能在多处理器系统上运行,将计算分解到多个线程中实现
计算密集型:执行流的大部分任务,主要以计算为主:加密解密,排序查找。
IO密集型:执行流的大部分任务是以IO为主的:刷磁盘,访问数据库,访问网络。
1.3 线程的缺点
性能损失
- 一个很少被外部事件阻塞的计算密集型线程往往无法与共它线程共享同一个处理器。如果计算密集型线程的数量比可用的处理器多,那么可能会有较大的性能损失,这里的性能损失指的是增加了额外的同步和调度开销,而可用的资源不变。
健壮性降低
- 编写多线程需要更全面更深入的考虑,在一个多线程程序里,因时间分配上的细微偏差或者因共享了不该共享的变量而造成不良影响的可能性是很大的,换句话说线程之间是缺乏保护的。
缺乏访问控制
- 进程是访问控制的基本粒度,在一个线程中调用某些OS函数会对整个进程造成影响。
比如:在多线程进程中,其中一个线程进行了一次I/O调用,这导致从用户态切换到内核态,把该进程置于阻塞状态,并切换到另一个进程(对用户级线程)。
编程难度提高
- 编写与调试一个多线程程序比单线程程序困难得多
1.4 线程异常
- 合理的使用多线程,能提高CPU密集型程序的执行效率
- 合理的使用多线程,能提高IO密集型程序的