进程
保存在硬盘上的程序运行以后,会在内存空间里形成一个独立的内存体,这个内存体有自己独立的地址空间,有自己的堆,上级挂靠单位是操作系统。操作系统会以进程为单位,分配系统资源(CPU时间片、内存等资源),进程是资源分配的最小单位。
线程
有时被称为轻量级进程(Lightweight Process,LWP),是操作系统调度(CPU调度)执行的最小单位。
线程独立拥有哪些资源?
线程上下文一般只包含CPU上下文及其他的线程管理信息,线程创建的开销主要取决于为线程堆栈的建立而分配内存的开销,这些开销并不大。线程还分为系统级别和用户级线程,用户级别线程对引起阻塞的系统调用的调用会立即阻塞该线程所属的整个进程,而内核实现线程则会导致线程上下文切换的开销跟进程一样大,所以经常的折衷的方法是轻量级进程(Lightweight)。在 Linux 中,一个线程组基本上就是实现了多线程应用的一组轻量级进程。线程的作用就在于充分使用硬件CPU,也就是我们说的并行。
线程的调度只有拥有最高权限的内核空间才可以完成,所以线程的切换涉及到用户空间和内核空间的切换,也就是特权模式切换,然后需要操作系统调度模块完成线程调度(taskstruct)
多个线程调用静态方法,是否会出现并发问题取决于,静态方法内部是否需要引用共享区内的静态变量。当线程调用静态方法时,都会创建一套临时变量,可见性是在这个线程内部,所以当多个线程调用静态方法时,并且这个静态方法没有引用外部静态变量的。不会有线程并发的问题。
协程
协程是一种用户态的轻量级线程,协程的调度完全由用户控制(与线程的主要区别)。协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈,直接操作栈则基本没有内核切换的开销,可以不加锁的访问全局变量,所以上下文的切换非常快。
协程在子程序内部可中断的,然后转而执行别的子程序,在适当的时候再返回来接着执行。
协程切换比线程切换快主要有两点:
- 协程切换完全在用户空间进行,线程切换涉及特权模式切换,需要在内核空间完成;
- 协程切换相比线程切换做的事情更少。
一般来说一次协程上下文切换最多就是几十ns 这个量级。协程由于是在用户态来完成上下文切换的,所以切换耗时只有区区100ns多一些,比进程切换要高30倍。单个协程需要的栈内存也足够小,只需要2KB
操作系统的设计,因此可以归结为三点
- 以多进程形式,允许多个任务同时运行;
- 以多线程形式,允许单个任务分成不同的部分运行;
- 提供协调机制,一方面防止进程之间和线程之间产生冲突,另一方面允许进程之间和线程之间共享资源。