Far better than putting synchronized
everywhere is to carefully reason about that invariants your classes need, then synchronize just enough to ensure those invariants. If you over-synchronize, you create two risks:
- deadlock
- liveness problems
Deadlock everyone knows. Liveness problems aren't related to the cost of synchronization, but instead to the fact that if you globally synchronize everything in a multithreaded application, then many threads will be blocked waiting to get a monitor because another thread is touching something unrelated but using the same monitor.
If you want to slap a keyword everywhere for safety, then I recommend use of final
instead of synchronized
. :)
Anything that you can make final
contributes to better thread safety and easier reasoning about what invariants need to be maintained by locks. To give an example, let's say you have this trivial class:
public class SimpleClass {
private volatile int min, max;
private volatile Date startTime;
// Assume there are many other class members
public SimpleClass(final int min, final int max) {
this.min = min;
this.max = max;
}
public void setMin(final int min) {
// set min and verify that min <= max
}
public void setMax(final int max) {
// set max and verify that min <= max
}
public Date getStartTime() {
return startTime;
}
}
With the above class, when setting min or max, you need to synchronize. The code above is broken. What invariant does this class have? You need to ensure that min <= max
at all times, even when multiple threads are calling setMin
or setMax
.
Assuming this is a big class with many variables and you synchronize everything, then if one thread calls setMin
and another thread calls getStartTime
, the second thread will be unnecessarily blocked until setMin
returns. If you do this with a class with many members, and assuming only a few of those members are involved in invariants that must be defended, then synchronizing everything will cause many liveness problems of this sort.