My architect always says that
Never synchronize on Boolean
I am not able to understand the reason why and would really appreciate if someone could explain with an example as to why it is not a good practice.
Reference Sample Code
private Boolean isOn = false;
private String statusMessage = "I'm off";
public void doSomeStuffAndToggleTheThing(){
// Do some stuff
synchronized(isOn){
if(isOn){
isOn = false;
statusMessage = "I'm off";
// Do everything else to turn the thing off
} else {
isOn = true;
statusMessage = "I'm on";
// Do everything else to turn the thing on
}
}
}
You should always
synchronizeon a constant object instance. If you synchronized on any object that you are assigning (i.e. changing the object to a new object) then it is not constant and different threads will be synchronizing on different object instances. Because they are synchronizing on different object instances, multiple threads will be entering the protected block at the same time and race conditions will happen. This is the same answer for synchronizing onLong,Integer, etc..To make matters worse, any
Booleanthat is created through autoboxing (isOn = true) is the same object asBoolean.TRUE(or.FALSE) which is a singleton in theClassLoaderacross all objects. Your lock object should be local to the class it is used in otherwise you will be locking on the same singleton object that other classes might be locking on in other lock cases if they are making the same mistake.The proper pattern if you need to lock around a boolean is to define a
private finallock object:Or you should also consider using the
AtomicBooleanobject which means you may not have tosynchronizeon it at all.In your case, since it looks like you need to toggle it on/off with threads then you will still need to
synchronizeon thelockobject and set the boolean and avoid the test/set race condition:Lastly, if you expect the
statusMessageto be accessed from other threads then it should be marked asvolatileunless you willsynchronizeduring the get as well.