聊聊线程模型:用户线程和内核线程

Posted 吉姆餐厅ak

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了聊聊线程模型:用户线程和内核线程相关的知识,希望对你有一定的参考价值。

概述

在以前的操作系统中,没有线程的概念。进程是资源分配和调度的最小单元。引入线程的概念以后,线程则是资源调度和分配的最小单元。引入线程的好处是可以提供并发量。在多核时代,一个进程可以做到真正的多线程并行。

线程又分为用户线程和内核线程。

  • 用户线程:语言层面创建的线程,比如 java语言中多线程技术,通过语言提供的线程库来创建、销毁线程。

  • 内核线程:内核线程又称为守护线程 或 Daemon线程,用户线程的运行必须依赖内核线程,通过内核线程调度器来分配到相应的处理器上。


多对一模型

用户级线程仅存在于用户空间中,此类线程的创建、撤销、线程之间的调度与通信,都无须通过内核来实现。用户进程利用语言层面提供的线程库来控制用户线程。由于线程在进程内切换的规则远比进程调度和切换的规则简单,不需要用户态/核心态切换,所以切换速度快。

优点:
在进程1中,线程的切换只需要依赖线程库,不需要依赖内核。相较于CPU在内核直接的切换,这种实现方式很轻量级,对系统资源消耗会小很多。所以,频繁的创建和销毁线程的成本也并不高。很明显,java中不是这么线程模型,java在使用线程时提倡避免创建和销毁线程。

缺点:
如果进程内的某一个线程发生阻塞,那整个进程就阻塞了。如上图,进程1绑定在内核线程1上,用户进程内只有线程2在运行。如果线程2阻塞,那整个进程1就阻塞了,因为内核并不知道线程1和线程3的存在。


一对一模型

聊聊线程模型:用户线程和内核线程

在 1:1 模型中,启动一个用户线程,就会同时创建一个内核线程(注意,这里是启动线程,不是创建线程)。
每个用户线程在其整个生命周期内,都会被映射或绑定到一个内核线程上。当用户线程声明周期结束,两个线程则一起退出。无论是用户进程的线程,或者是系统进程的线程,他们的创建、撤销、切换都是依靠内核实现的。所以该模式下,CPU在线程的切换开销比较大。

Java 语言采用的便是这种线程模型。

优点:
1)在多处理器中,能够实现同一个进程中,多个线程同时并行。
2)当一个线程阻塞时,同一个进程中的其他线程可以继续运行,并发能力比较强。

缺点:
每个用户线程的启动和运行都必须创建一个内核线程,不适合频繁的创建和销毁。


多对多模型 

多对多模型是从上面两种模型演进而来。线程创建完全在用户空间中完成,线程的调度和同步也在应用程序中进行. 一个应用程序中的多个用户级线程被映射到一些(小于或等于用户级线程的数目)内核级线程上。

聊聊线程模型:用户线程和内核线程

如上图:线程1和线程2同时绑定到内核线程1上,如果线程1因为系统调用发生阻塞,进程1则会调度线程2执行,充分利用内核线程资源。多对多模型依赖自身调度与系统调度协同工作,而且并不是所有操作系统都支持多对多的混合模型,操作系统内核开发者一般不会使用,所以更多时候是作为第三方库的形式出现,而Go语言中的runtime调度器就是采用的这种实现方案。


协程

协程可以理解就是一种用户空间线程。拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈,通过这种方式可以实现协程见的协作执行。
聊聊线程模型:用户线程和内核线程
目前主流语言基本上都选择了多线程抢占式执行模型,抢占式调度执行顺序无法确定,所以使用线程时需要非常小心地处理同步问题,而协程完全不存在这个问题。协程可以由程序员自己写的调度策略,其通过协作而不是抢占来进行切换。另外协程是在用户态完成创建,切换和销毁,不需要绑定内核,成本相对较低。


用户线程和内核交互流程 

聊聊线程模型:用户线程和内核线程


其中第3、4、5、10步骤涉及到用户线程与内核交互:


3:应用程序收到响应。然后创建并启动用户线程来处理响应请求,同时也会创建一个内核线程,并将二者绑定。

4:系统调用。可以是网络io,也可以是磁盘io。这里是磁盘io。

5:内核调起驱动,查询磁盘数据并返回。

10:系统调用。应用程序处理完查询的数据之后,写入socket channel,进行返回。


总结 

Java中的线程模型(1:1模型)之所以避免频繁创建线程,就是为了避免 cpu 在内核之间的切换。而 Go 语言中,如果用户线程发生阻塞,cpu 不需要切换内核线程,因为内核线程中有其他可运行的用户线程。


聊聊线程模型:用户线程和内核线程


https://blog.csdn.net/woshilijiuyi?ref=toolbar
更多技术干货等你来拿

长按二维码关注

你点的每个“在看”,我都认真当成了喜欢

以上是关于聊聊线程模型:用户线程和内核线程的主要内容,如果未能解决你的问题,请参考以下文章

进程和线程

多线程编程总结

线程池

线程池

死磕 java线程系列之线程模型

线程的3种实现方式--内核级线程, 用户级线程和混合型线程