进程与线程¶
进程¶
进程是系统进行资源分配和调度的一个独立单位。每个进程都有自己的独立内存空间,不同进程通过进程间通信来通信。由于进程比较重量,占据独立的内存,所以上下文进程间的切换开销(栈、寄存器、虚拟内存、文件句柄等)比较大,但相对比较稳定安全。
线程¶
线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源。线程间通信主要通过共享内存,上下文切换很快,资源开销较少,但相比进程不够稳定容易丢失数据。
协程¶
**协程是一种用户态的轻量级线程,**协程的调度完全由用户控制。协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈,直接操作栈则基本没有内核切换的开销,可以不加锁的访问全局变量,所以上下文的切换非常快。
- 无需线程上下文切换的开销
- 无需原子操作锁定及同步的开销
- 方便切换控制流
IO密集型 : 线程和协程
CPU密集型:进程
进程与线程区别¶
- 根本区别:进程是操作系统资源分配的基本单位,而线程是处理器任务调度和执行的基本单位
- 资源开销:每个进程都有独立的代码和数据空间(程序上下文),程序之间的切换会有较大的开销;线程可以看做轻量级的进程,同一类线程共享代码和数据空间,每个线程都有自己独立的运行栈和程序计数器(PC),线程之间切换的开销小。
- 包含关系:如果一个进程内有多个线程,则执行过程不是一条线的,而是多条线(线程)共同完成的;线程是进程的一部分,所以线程也被称为轻权进程或者轻量级进程。
- 内存分配:同一进程的线程共享本进程的地址空间和资源,而进程之间的地址空间和资源是相互独立的
- 影响关系:一个进程崩溃后,在保护模式下不会对其他进程产生影响,但是一个线程崩溃整个进程都死掉。所以多进程要比多线程健壮。
- 执行过程:每个独立的进程有程序运行的入口、顺序执行序列和程序出口。但是线程不能独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制,两者均可并发执行
线程切换代价小的原因¶
任务调度的开销主要有
- CPU执行任务调度的开销,主要是进程上下文切换的开销
- 进程调度还是线程调度都是必须的,所以无关
- 任务调度后,CPU Cache/TLB不命中,导致缺页中断的开销
- 每个进程都有自己的虚拟地址空间,进程内的所有线程共享进程的虚拟地址空间。
- 把虚拟地址转换为物理地址需要查找页表,页表查找是一个很慢的过程,因此通常使用Cache(TLB)来缓存常用的地址映射加速页表查找。当进程切换后页表也要进行切换,页表切换后TLB就失效了,cache失效导致命中率降低,那么虚拟地址转换为物理地址就会变慢。
- 进程切换上下文,处理器中所有已经缓存的内存地址都会刷新,触发更多的缺页中断。线程不会。
进程通信方式¶
匿名管道¶
- 管道是半双工的,数据只能向一个方向流动;需要双方通信时,需要建立起两个管道。
- 只能用于父子进程或者兄弟进程之间(具有亲缘关系的进程);
- 单独构成一种独立的文件系统,只存在于内存的文件。实质是一个内核缓冲区
- 写入无名管道的数据超过其最大值,写操作将阻塞,如果管道中没有数据,读操作将阻塞,如果管道发现另一端断开,将自动退出。
有名管道¶
- 有名管道以磁盘文件的方式存在,可以实现本机任意两个进程通信
- 有名管道在打开时需要确实对方的存在,否则将阻塞
信号¶
- 信号可以在任何时候发给某一进程,而无需知道该进程的状态。若当前并未处于执行状态,则该信号就有内核保存起来,直到该进程回复执行
- 如果一个信号被进程设置为阻塞,则该信号的传递被延迟,直到其阻塞被取消
消息队列¶
- 消息队列是存放在内核中的消息链表,只有操作系统重启或显式删除时,才真正被删除
- 允许一个或多个进程向它写入与读取消息
- 不一定按顺序,可以按消息类型
共享内存¶
- 多个进程可以可以直接读写同一块内存空间,是最快的可用IPC形式
- 需要依靠某种同步机制(如信号量)来达到进程间的同步及互斥
信号量(PV)¶
- 信号量是一个计数器,用于多进程对共享数据的访问,信号量的意图在于进程间同步
socket¶
- 一般不同主机之间的进程进行双向通信
- 应用层、传输层、网络层、数据链路层、物理层
线程通信方式¶
- 等待唤醒:wait, notify
- Volatile, sync
- 忙等待:空循环
- JUC