@
thomaswang 操作系统提供的原生线程,是由内核实现的,当发生时钟中断,内核的终端处理流程会切换线程上下文并调度到另一个线程继续执行;原生线程是必须依赖硬件和内核共同工作的,也就是你说的“内核线程”
一般来说一个原生线程只干一件事,但有时候不满足需要
现在不考虑原生线程,假设你要在一个单一线程里模拟同时执行多个任务能实现吗
—— 是可以的,比如实现一个虚拟机:
def main_loop():
..for t in tasks:
....c = next(task.codes)
....ctx = task.context
....exec_opcode(c,ctx)
取得每个 task 的下一条指令,执行一遍然后马上返回主循环,每个 task 中执行流都会往下走,但这都完全发生在同一个线程里
当然拆到这么细粒度需要的代价非常大(实现虚拟机过于复杂而且慢得很)刚好很多语言提供了协程或者撸协程用的 feature,比如 yield:
def fake_sleep():
..yield
def thread1():
..while True:
....print('thread1')
....yield from fake_sleep()
def thread2():
..while True:
....print('thread2')
....yield from fake_sleep()
while True:
..for t in [thread1(),thread2()]:
....t.send(None)
每一个 fake_sleep 都是调度点,此时我们就可以把 thread1 和 thread2 看做是“线程”(协程),在一段时间内这两个函数会“并行”执行然后交替输出 thread1/thread2
于是我们就可以用协程来模拟多任务并行了,只不过需要手动实现切换 task 的代码
以上你已经了解了 用户线程内核线程 1:1 以及 N:1 的模型
那么任意比例的模型也就是把若干个 N:1 模型放进几个真正的原生线程里而已,当然其中复杂度和涉及的细节都会多很多,此处不展开
可以看到这几种模型其实跟内核代码怎么切换根本就没什么关联,是两种意义层次