I have a processor with two cores c1 and c2. I have seven threads t0, t1, t2, t3, t4, t5 and t6. t0 is the main thread.
From t0 I create t1 and t2 to handle certain tasks from data d0 obtained from t0. Both t1 and t2 work to produce data d0a and d0b they then feed to the main thread to produce d0a d0b = data d1 (i.e. threads t1 and t2 wait (join()
) for each other to be idle before sharing their intel (d0a and d0b obtained from d0) with the main thread to produce d1).
In order to help speed up the process at t1 it spawns thread t3 and t4 to help produce d0a likewise the process at t2 also spawns t5 and t6 to help produce d0b.
Let’s assume c1 handles t1, t3 and t4 then c2 handles t2, t5 and t6 by default
Say t1 with the assistance of t3 and t4 after producing d0a finished way ahead of the commencement of the process at t2. Would c1 help c2 finish up the process at t2 for example by handling one of it’s sub threads (t5 or t6).
Can processor cores start queued threads whenever threads assigned to them are idle.
This question is particularly tagged with java and windows because I am especially interested in how it applies. Other answers are also welcome
CodePudding user response:
Can processor cores start queued threads...
Processor cores know nothing about threads. Processor cores execute streams of instructions. That's all they do.
The operating system scheduler knows about threads, and in particular, it knows the operational state of each thread. In some hypothetical OS, there are states called running
, runnable
(the thread wants to run but it lacks a CPU to run on), and blocked
(the thread is waiting for something.) In a real OS, there may be different kinds of blocked
, and there may be other states like dead
, but we don't need to talk about those here.*
The OS also has a number of queues† that hold the contexts of non-running
threads; There is a run queue that contains all of the runnable
threads, and there typically is a different queue for each different reason that a thread might be blocked
. (E.g., for each mutex lock, there is a queue of threads waiting to acquire the lock.)
The job of the OS scheduler is to decide when to preempt some running thread A, and choose a different runnable
thread B to take its place. The scheduler;
- Interrupts (i.e., takes control of) the CPU that is running thread A,
- Changes thread A's state from
running
torunnable
, - Moves the thread A's context to the back of the run queue,
- Removes thread B from the run queue,
- Changes the state of thread B from
runnable
torunning
, - Loads thread B's context onto the CPU, and
- lets the CPU return to executing application code.
...whenever threads assigned to them are idle?
Threads are never idle.‡ Threads either are blocked
or runnable
if not running
. A CPU can be idle if there are no runnable
threads that can be moved onto it. When the CPU is idle, it typically executes the operating system's idle loop, which looks like,
while (true) {
putCPUIntoLowPowerState();
}
The only way out of the idle loop is for the CPU to be interrupted, as described above.
* Java's Thread.State
enumeration does not recognize any difference between running
and runnable
. Those both are wrapped up in Thread.State.RUNNABLE
. Also, Java splits my blocked
into Thread.State.BLOCKED
(the thread is waiting to enter a synchronized
block) and Thread.State.WAITING
(the thread is waiting for any other reason.)
† Not actually strict FIFO queues (thanks @NateEldredge), but "queue" is the traditional name. They are the containers in which threads reside when they await whatever it is they are waiting for. The scheduler may consider various factors (e.g., the thread's priority) besides just how long the thread has been waiting when deciding which thread to take from one queue and move to a CPU or to another queue.
‡ I mean that from the point of view of the OS scheduler. An application might consider one of its threads to be "idle," but the OS knows nothing about what the application threads are supposed to do. As far as the OS is concerned, a thread either is running
, or it is runnable
, or it is blocked
.