14.2. Thread Terminology¶
14.2.1. Working Definitions¶
14.2.2. Parallel Execution¶
When a program runs on a computer, its instructions are sent by the operating system to the computer’s central processing unit (or CPU) where the execution of those instructions actually takes place. Early CPUs could only execute a single sequence of instructions at any given time; however, modern CPUs are built with multiple internal processing units, each of which is called a core, that can each run their own sequence of instructions in parallel (i.e., at the same time) with all the other cores.
The example in the diagram below illustrates the parallel execution of
a main
thread and another thread named t1
. Each vertical line
is a timeline that starts at the top and ends at the bottom, and the
rectangular areas along the line illustrate when the instructions in a
thread are executing on some core. Since the rectangular areas for
each thread overlap some regions of time along the timeline, they are
executing in parallel.
14.2.3. Concurrent Execution¶
When the number of instruction sequences exceeds the number of cores, the operating can still give the appearance that they are executing at the same time by switching between those instruction sequences very quickly, sending a little bit of each sequence to a core for execution at any given time. Since these sequences are not actually executing in parallel but still appear to be, we call this concurrent execution.
The example in the diagram below illustrates the concurrent execution of
a main
thread and another thread named t1
. Each vertical line
is a timeline that starts at the top and ends at the bottom, and the
rectangular areas along the line illustrate when the instructions in a
thread are executing on some core. Since the rectangular areas for
each thread never overlap, they are said to be executing concurrently
so long as the operating system is switching between them really fast.
In practice, programs involving several threads execute concurrently most of the time and in parallel some of the time, depending on which core the operating system sends the subsequences of the thread’s instructions to.
14.2.4. Additional Notes¶
Most operating systems use processes to represent and store the instructions and state of a running program in order to facilitate their concurrent execution – it gives the operating a set of objects to switch between. Likewise, programs that need to facilitate concurrent execution of different parts of the program typically use threads to represent and store the instructions and state of a running method (and its calls to other methods) – it gives the program a set of objects that can also be switched between.
On a Unix machine, you can typically use the ps command to list the processes that the operating system is currently managing and switching between:
ps -e
PID TTY TIME CMD
1 ? 01:51:39 systemd
2 ? 00:00:40 kthreadd
4 ? 00:00:00 kworker/0:0H
6 ? 00:00:47 ksoftirqd/0
7 ? 00:00:15 migration/0
8 ? 00:00:00 rcu_bh
9 ? 02:02:48 rcu_sched
10 ? 00:00:00 lru-add-drain
11 ? 00:00:34 watchdog/0
...
[typically continues for hundreds lines]
To count the number of processes, you can pipe the output into wc to see how many lines are produced. In the example below, the output suggests that there are 743 processes managed by the operating system that have not yet terminated – we subtract one to account for the header line produced by ps:
ps -e | wc -l
744
To see extended information about the process managed by the operating system that were started by your user account but have not yet terminated, use the -x option with ps:
ps -x
PID TTY STAT TIME COMMAND
5973 ? S 0:00 sshd: myid@pts/48
5974 pts/48 Ss 0:00 -bash
27886 pts/48 R+ 0:00 ps -x
In the last example, sshd
is handling the the SSH connection for
the user, -bash
is their login shell, and ps -x
is the
instance of ps that is being run to produce the output
(i.e., ps includes itself in its output).