线程模型

内核级线程模型


在一个系统上实现线程模型的方式有好几种,因内核和用户空间提供的支持而有一定程度的级别差异。最简单的模型是在内核为线程提供了本地支持的情况,每个内核线程直接转换成用户空间的线程。这种模型称为“1:1线程模型(threading)”,因为内核提供的线程和用户的线程的数量是1:1。该模型也称为“内核级线程模型(kernel-level threading)”,因为内核是系统线程模型的核心。


Linux 中的线程就是“1:1线程模型”。在Linux内核中只是简单地将线程实现成能够共享资源的进程。线程库通过系统调用 clone() 创建一个新的线程,返回的“进程”直接作为用户空间的线程。也就是说,在Linux上,用户调用线程和内核调用线程基本一致。


用户级线程模型


和“内核级线程模型”模型相反,“用户级线程模型(user-level threading)”是“ N:1线程模型(threading)”。在“用户级线程模型”模型中,用户空间是系统线程支持的关键,因为它实现了线程的概念。一个保护 N 个线程的进程只会映射到一个内核进程——即 N:1。该模型很少甚至不包含内核支持,但用户空间代码有很多,包括用来管理线程的用户空间调度器以及以非阻塞模式捕捉和处理 I/O 机制。用户级线程模型的优点在于上下文切换几乎是零成本的,因为应用本身可以决定何时运行哪个线程,不需要内核操作。其缺点在于由于支持线程的内核实体只有一个,该模型无法利用多处处理器,因此无法提供真正的并行性。在现代的操作系统中,这个缺点很严重,尤其在Linux上,减少上下文切换代价带来的好处微乎其微,因为Linux支持非常低成本的上下文切换。


在Linux上,虽然也存在用户级线程库,大多数库提供的都是“1:1线程库模型”。


混合式线程模型


如果我们把内核级线程模型和用户级线程模型结合起来,结果会怎样呢?是否可以实现“1:1线程模型”带来的真正并行性,同时还可以利用“N:1线程模型”的零成本切换?确实可以,只不过这个模型很复杂。“N:M线程模型”也称为“混合式线程模型”,正是希望能够充分利用前两种模型的优点:内核提供一个简单的线程概念,而用户空间也实现用户线程。然后,用户空间(可能和内核结合起来)决定任何把N个用户线程映射到M个内核线程中,其中 N>=M。


由于实现机制不同,映射方法也有区别,但是经典策略是不要在一个内核线程中支持大部分的用户线程。一个进程可能包含几百个用户线程,但只包含几个内核线程,由几个处理器(每个处理器至少有一个内核线程支持对系统的完全使用)和阻塞式 I/O 处理。正如我们所想象的,该模型很难实现。由于在Linux中上下文切换成本很低,很多系统开发人员不觉得这个方法可行,1:1线程模型在Linux系统中还是很普遍。

协调程序


协调程序(coroutines and fibers)提供了比线程更轻量级的执行单位(coroutines 和 fibers 的区别在于前者是编程语言中的概念,后者是系统中的概念)。和用户级线程模型类似,协同程序也属于用户空间范畴,但是和用户级线程模型不同的是,几乎不存在用户空间对协同程序的调度和执行的支持。相反,它们是协作式调度,支持显式放弃一个程序而去执行另一个。协同程序和子程序(普通的C/C++函数)的差别非常微小。实际上,你也可以把子程序作为特殊的协调程序。协同程序更侧重于程序流的控制,而不是并发性。


Linux本身并不支持协同程序,可能还是因为其上下文切换已经非常快,不需要比内核线程性能更好的结构。编程语言 Go 为Linux提供了对类似协同程序的语言级支持,称为 Go-routines。协同程序支持区分编程规范和 I/O 模型,这是值得关注的。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值