If an outcome is deterministic, then that outcome is not in any way dependent on chance. The heads-or-tails outcome of flipping a coin where both sides are heads is deterministic because we know that no matter how we flip it, it will always come up heads.
This is how we want our programs to be – deterministic. Unless we explicitly include an element of randomness, we want our programs to behave the same way each time we run them.
A singly-threaded program is inherently deterministic. When the program has a single thread, the order in which those tasks are executed is the same every time.
In multi-threaded programs, since the tasks are executed concurrently, the sequential order of tasks is not guaranteed. In other words, they are non-deterministic and to some extent, random. When this randomness affects the behavior of the program, we have what is known as a race condition.
Consider the following situation depicted in the animation to the right. We have a program with the expression
x = 3 and two threads. The job of
thread_one is to execute
x = x * 2 and the job of
thread two is to execute
x = x + 1.
In case 1,
thread_one executes before
thread_two and by the end of our program’s execution,
x has a value of
In case 2,
thread_two executes before
thread_one which means
x will equal
8 by the end of execution.
In the following exercises, we will look at another example of a race condition as well as ways we can synchronize our programs in order to avoid them.
Click Next when you’re ready to move on to the next exercise.