线程的概念
1.什么是线程?
在以前学习的时候,我们学习了进程,而对于线程,其实就是进程中的一条执行流程。
但是在linux操作系统下,我们是如何调度一个进程呢?
看下图:
我们知道cpu调度进程实际上是通过这个进程的pcb来调度的,所以我们也说一个进程的本质就是pcb,而线程是的定义是进程的一条执行流,但是,在linux下的执行流是通过pcb实现的,所以,线程的本质也是一个pcb。并且要注意的是,在一个进程中,可以有多条执行流,那么在一个进程中就会有多个pcb,而对于这些线程的pcb和进程又有什么区别呢?
对于上图,我们发现,对于事件1,事件2,事件3,我们都是通过一个pcb调度的,这明显是一个单线程下的操作,所以对于事件1,事件2,事件3在相同的时间只能运行其中一个事件,而如果我们想要让事件1,2,3 “ 同时 ”运行起来,那么我们就会不由自主的想起多线程的情况,那么多线程是如何操作的呢?
请看下图:
如果我们向让其在“ 相同 ”的时间运行起来,那么就给每个事件都包装一个pcb,然后通过cpu去调度这些pcb就可以实现在“ 相同 ”的事件运行起来,这其实就是我们所说的线程了,这样我们也可以得出,其实一个进程就是pcb,线程也是pcb,并且cpu调度的单位就是pcb,所以cpu调度的基本单位就是线程。
但是,上图是错误的,因为三个线程是我们在主线程下创建出来的,如果每个pcb都是全部独立的,那么系统的开销就太大了,所以正确的图应该是下图:
所以从上面的图,我们可以看出来:其实多线程是共享了很多程序运行所需要的资源,他们并不是完全独立的,并且在linux下的pcb其实还有一个新名字叫做轻量级进程。
总结:
- 在一个程序里面的一个执行线路就叫做线程。
- 一切进程至少有一个线程。(这意味着,其实进程就是一个主线程)
- 线程是在进程内部运行,本质是在进程地址空间运行。
- 在linux系统中,在cpu眼里,看到的pcb都要比传统的进程更加轻量化。
- 透过虚拟地址空间,可以看见进程的大部分资源,将进程资源合理的分配给每个执行流,就形成了线程执行流。
线程与进程之间的关系
首先我们应该知道的:
- 操作系统调度的基本单位是:进程。(因为对于进程而言,操作系统要给其分配资源,但是不会给线程分配资源)
- 操作系统调度的最小单位:线程。(主线程)
- cpu调度的基本单位:线程。(pcb)
其实线程就是进程的一个实体,是cpu调度和分派的基本单位,他是比进程更小的并且能独立运行的基本单位。
线程与进程之间的关系如下:
1.一个线程只能存在在一个进程中,而一个进程可以拥有多个线程。
2.进程通过操作系统分配资源,同一个进程下的所有线程都共享着这些资源。
3.cpu调度的基本单位是线程,所以真正被cpu调度的是线程,所以这也就是“ 同时 ”要加双引号,其实说白了就是cpu的分时机制,还是运行那么一小段时间,可惜我们人是觉察不到的。
同一个进程下的线程与线程之间的关系
线程,我们知道是pcb,并且同一进程下的线程是共享着进程所分配的资源的,但是对于多线程中的线程,他们其实并不是完全共享的,他们肯定有独立的一部分,不然怎么独立运行起来,所以就会出现其有独立的部分和共享的部分:
1.相同部分:
- 虚拟地址空间。(可以用于线程间的通信)
- 信号处理模式。(对于信号,由于信号是传递给进程的,但是进程其实就是一个主线程,然后如果说进程下有多个线程,那么这些线程其实都会接收到这个信号的,所以对于信号的处理,正常情况下应该是当前pcb运行到那个线程下了,那个线程就去处理)
- 工作路径。(一个程序运行起来,就会在当前所在路径下去运行)
- I/O信息。
- 用户id和组id。
注意:对于进程,我们都知道是有个进程id的,但是对于进程下的线程他有一个组id,叫做tgid(thread group id,也就是组id)是相同的,用来表示这些线程是同一进程下的。
2.独有部分
- 线程id。(这是用来区别同一进程下的不同的线程的)
- 栈。(避免使用相同的栈,在多线程的情况下出现函数调用栈混乱,出现不可控制的后果)
- 寄存器。(用来保存当前的线程运行到什么位置)
- errno。(当当前线程出现错误时,应该返回当前线程出现的错误)
- 信号屏蔽字。(用来阻塞信号,这是因为特殊情况下,有些线程是很重要的,他要一直运行,如果被打断会出现严重的后果,所以我们一般会用此其去屏蔽传来的信号,防止信号将其打断)
- 调度优先级。
注意:在主线程中,我们一般不会让其退出,因为主线程就是这个进程的主流,它如果退出了,那么它旗下的所有线程都会退出。
多线程与多进程在任务处理中的优缺点
1.多线程:
- 线程间通信非常灵活。(包含进程间通信方式在内,并且还有全局数据,也可传参)
- 线程的创建于销毁成本更低。(因为资源很多都是共享来的)
- 线程间的切换调度成本较低。(因为资源大多是共享的,所以保存信息少)
2.多进程:
- 独立性高,稳定性强。
3.共同有点:
- cpu密集型程序:程序中几乎都是cpu数据运算。
多核cpu:充分利用了cpu资源。
注意:同一进程下的线程并不是越多越好,如果超出了处理器的数量(核的数量),那么就会有较大的性能损失(增大了额外的同步和调度的开销,并且可用的资源还不变)。 - I/O密集型程序:程序中大多都是I/O操作。(I/O操作被重叠,不同的线程可以等待不同的I/O操作)
所谓I/O:等待I/O就绪,拷贝数据。