Threads and Concurrent Programming
Threads may be seen as methods that execute at "the same time" as other methods. Normally, we think sequentially when writing a computer program. From this perspective, only one thing executes at a time. However, with today's multi-core processors, it is possible to literally have several things going on at the very same time while sharing the same memory. There are lots of ways that this is done in the real world, and this chapter goes over them in a way that you can apply to your own projects.
14.3 From the Java Library: java.
The Asynchronous Nature of Threaded Programs
Threads are asynchronous. This means that the order of execution and
the timing of a set of threads are unpredictable, at least from the programmer’s point of view. Threads are executed under the control of the
scheduling algorithm used by the operating system and the Java Virtual
Machine. In general, unless threads are explicitly synchronized, it is impossible for the programmer to predict when and for how long an individual thread will run. In some systems, under some circumstances, a thread might run to completion before any other thread can run. In other
systems, or under different circumstances, a thread might run for a short
time and then be suspended while another thread runs. Of course, when
a thread is preempted by the system, its state is saved so that its execution
can be resumed without losing any information.
One implication of a thread’s asynchronicity is that it is not generally
possible to determine where in its source code an individual thread might
be preempted. You can’t even assume that a thread will be able to complete a simple Java arithmetic operation once it has started it. For example,
suppose a thread had to execute the following operation:
This operation computes the sum of 5 and 3 and assigns the result to N. It
would be tempting to think that once the thread started this operation, it would be able to complete it, but that is not necessarily so. You have to remember that Java code is compiled into a rudimentary bytecode, which
is translated still further into the computer’s machine language. In machine language, this operation would break down into something like the
following three steps:
Although none of the individual machine instructions can be preempted,
the thread could be interrupted between any two machine instructions.
The point here is that not even a single Java language instruction can be
assumed to be indivisible or unpreemptible. Therefore, it is impossible to
make any assumptions about when a particular thread will run and when
it will give up the CPU. This suggests the following important principle
Threads are of multithreaded programs:
As we will see, this principle plays a large role in the design of multithreaded programs.