我有一个有两个内核c1和c2的处理器。我有七个线程 t0、t1、t2、t3、t4、t5 和 t6。t0 是主线程。
从 t0开始,我创建了 t1 和 t2 来处理从 t0 获得的数据 d0 中的某些任务。t1 和 t2 都工作以生成数据 d0a 和 d0b,然后它们馈送到主线程以产生 d0a + d0b = 数据 d1(即线程 t1 和 t2 等待 (join()
) 彼此空闲,然后与主线程共享它们的英特尔(从 d0 获得的 d0a 和 d0b)以产生 d1)。
为了帮助加快 t1 处的进程,它会生成线程 t3 和 t4 以帮助生成 d0a,同样,t2 处的进程也会生成 t5 和 t6 以帮助生成 d0b。
假设 c1 处理t1、t3 和 t4,然后 c2 默认处理 t2、t5 和 t6
在t3 和 t4 的帮助下说 t1,在 t2 处开始处理之前生产 d0a 完成。c1 会帮助 c2 在 t2 处完成进程,例如通过处理它的子线程之一(t5 或 t6)。
只要分配给它们的线程空闲,处理器内核是否可以启动排队的线程。
这个问题特别被标记为java和windows,因为我对它如何应用特别感兴趣。也欢迎其他答案
处理器内核可以启动排队的线程吗...
处理器内核对线程一无所知。处理器内核执行指令流。这就是他们所做的一切。
操作系统调度程序知道线程,特别是它知道每个线程的操作状态。在一些假设的操作系统中,有称为running
的状态,runnable
(线程想要运行,但它缺少 CPU 来运行)和blocked
(线程正在等待某些东西)。在真实的操作系统中,可能会有不同类型的blocked
,也可能有其他状态,如dead
,但我们不需要在这里谈论这些。
操作系统还具有许多队列†用于保存非running
线程的上下文;有一个包含所有runnable
线程的运行队列,并且对于线程可能blocked
的每个不同原因,通常都有一个不同的队列。(例如,对于每个互斥锁,都有一个线程队列等待获取锁。
操作系统调度程序的工作是决定何时抢占某个正在运行的线程 A,并选择不同的线程 Brunnable
来取代它。调度程序;
- 中断(即控制)运行线程 A 的 CPU,
- 将线程 A 的状态从
running
更改为runnable
, - 将线程 A 的上下文移动到运行队列的后面,
- 从运行队列中删除线程 B,
- 将线程 B 的状态从
runnable
更改为running
, - 将线程 B 的上下文加载到 CPU 上,并且
- 让 CPU 返回到执行应用程序代码。
。每当分配给它们的线程处于空闲状态时?
线程永远不会处于空闲状态‡ 线程要么blocked
,要么runnable
(如果不running
)。如果没有可以移动到 CPU 上的runnable
线程,则CPU可能处于空闲状态。当 CPU 空闲时,它通常会执行操作系统的空闲循环,如下所示:
while (true) {
putCPUIntoLowPowerState();
}
如上所述,摆脱空闲循环的唯一方法是中断 CPU。
* Java 的Thread.State
枚举无法识别running
和runnable
之间的任何区别。这两个都包裹在Thread.State.RUNNABLE
.此外,Java 将我的blocked
拆分为Thread.State.BLOCKED
(线程正在等待进入synchronized
块)和Thread.State.WAITING
(线程正在等待任何其他原因)。
† 实际上不是严格的FIFO队列(感谢@NateEldredge),但"队列"是传统名称。它们是线程在等待它们正在等待的任何内容时驻留在其中的容器。调度程序可以考虑各种因素(例如,线程的优先级),除了线程在决定从一个队列中获取哪个线程并移动到 CPU 或另一个队列时等待的时间。
‡ 我的意思是从操作系统调度程序的角度来看。应用程序可能将其线程之一视为"空闲",但操作系统不知道应用程序线程应该做什么。就操作系统而言,线程要么running
,要么runnable
,要么blocked
。