We've seen that by using thread synchronization,
we can prevent threads from seeing the intermediate states
during method execution by other threads.
The synchronized modifier acquires a lock on the object
at the beginning of the execution of the method and releases it
after the method is done executing,
thereby making the method appear as if it were executed in a
single atomic step.
Deadlock occurs when there is a cycle of threads waiting for each
We can draw a diagram of this situation as a graph,
where an arrow represents a "waiting for" relation.
Or, to be more specific,
we can add the objects (resources) to the graph.
Here, and arrow from a thread to a resource means the thread is
waiting for a lock on that resource,
and an arrow from a resource to a thread means the reasource is
locked by the thread.
if there is a cycle in the graph,
deadlock exists and all threads involved in the cycle
will be blocked forever.
Java does not detect this situation--you'll notice it only when
things come to a grinding halt.
And no amount of testing will guarantee deadlock can't happen
unless you test all possible interleavings.
it's important to reason carefully about your program in order
to prove that deadlock cannot occur.
You can avoid problems like the example above by making sure
that synchronized methods never call (directly or indirectly)
synchronized methods on other objects (that could be locked by
calling another synchronized method within the same object is
since you already have the lock.
To fix the problem above means either dropping
synchronized from getX,
or changing the interface so setMaximum takes in two values,
and therefore has no need to call getX on another object.
Note: If two threads may access shared data through
methods that are not synchronized,
its important to declare those variables as volatile so
the compiler will not perform optimizations that result in local
private volatile int x;
Volatile here tells the compiler that multiple threads may
access the data.
lets look at another kind of situation that can cause deadlock.
If the counter gets to zero,
the thread will suspend itself.
the resetCounter method is supposed to wake it up.
any thread that tries to call resetCounter will be blocked
waiting for takeStep to return--but it won't return because it's
Solution: call suspend within run(),
outside the synchronized method.