Card 01/ 09
synchronized: One Thread at a Time, on a Chosen Object
Which object a synchronized block locks decides whether two threads exclude each other.
synchronized marks a region of code that only one thread may be inside at a time. What enforces it is a lock, and every Java object has one: a thread must take the object's lock to enter, and other threads wait until it is released.
A withdrawal reads a balance, checks it and writes it back. Making that one uninterruptible step is not something an atomic class, such as AtomicLong, which makes one read-modify-write indivisible, can do, because it combines a check and a write that must happen together:
class Account {
private long pence;
synchronized void withdraw(long amount) {
if (amount <= pence) {
pence -= amount;
}
}
}The keyword on line 4 is shorthand. A synchronized instance method locks this, the object the method was called on, for the whole of its body, and the long form says so explicitly:
void withdraw(long amount) {
synchronized (this) {
if (amount <= pence) { pence -= amount; }
}
}Two threads calling withdraw on the same Account now take turns. Two threads calling it on two different accounts do not wait for each other at all, because each takes a different object's lock.
So the question to ask of any synchronized is not whether it is there but which object it locks. Threads are only kept apart when they lock the same one, and nothing in the syntax makes that obvious.
← → move through sections and cards