Before preceeding with threads we should first look again at what the basics of how they work.
We can use a simple crude model of a processor to illustrate the concepts involved.
When a program is run, the registers contain the current state of execution, which includes a pointer to the memory address of the next instruction.
When the program flow jumps to another location, e.g. when a method call occurs, the current register values are saved on a stack and a new next-instruction-address, as well as other register values are loaded.
When the flow returns to the original location, the old register values are popped off the stack and loaded back into the registers.
Note: to allow for many layers of method calls, the stack should be as large as possible.
Multi-threading involves maintaining more than one stack and switching between them.
This diagram illustrates multi-threading:
A separate stack in this case is maintained for each thread.
Suppose Thread 1 represents the initial process flow. At some point, determined by the multi-processing architecture, the processing is stopped, and the current registers are saved on the Thread 1 stack.
The top of the Thread 2 stack replaces the registers and then the processing continues.
At some point in time, the processing stops again and the current registers are saved on the Thread 2 stack. The Thread 3 stack values are popped off and fill the registers and processing continues.
This switching in and out of the different thread stacks proceeds in this manner until the program finishes. Individual threads may finish during the processing and new ones created.
This illustrates how multiple threads are created within a single process.