Multi-thread concurrency can be achieved in JAVA through the synchronized statement. Using synchronized code blocks, the JVM ensures that only one thread can hold the lock on a certain object at the same time. The lock mechanism enables multiple threads to safely access critical resources.
The synchronization code is written as follows:
Code 1:
Object obj = new Object(); ... synchronized(obj) { //TODO: Access critical resources} JAVA's multi-threading is always full of traps. If we use Boolean as the synchronized object, the following two situations may occur:
1. It is thought that one object is locked, but different objects are actually synchronized.
Code 2:
private volatile Boolean isTrue = false; publich void aMethod() { ... synchronized(isTrue) { isTrue = !isTrue; //TODO: Access critical resources isTrue = !isTrue; } ... } At first glance, there is nothing wrong with the above code. Because synchronized(isTrue) is used, only one thread can access critical resources at the same time, but this is not the case. Because the two constants false and true correspond to two different objects. When isTrue changes, it is likely that different threads will synchronize different objects. JAVA's automatic boxing will change false to Boolean.FALSE and true to Boolean.TRUE (this also shows that if false is changed to Boolean.FALSE, the result will be the same). Write the test code for one of the above situations as follows:
Code 3:
public class BooleanTest { private volatile Boolean isTrue = Boolean.FALSE; //It's the same if you use false here public void aMethod() { for(int i=0;i<10;i++) { Thread t = new Thread() { public void run() { synchronized(isTrue) { isTrue = !isTrue; System.out.println(Thread.currentThread().getName() + " - isTrue=" + isTrue); try{ Double ran = 1000 * Math.random(); Thread.sleep(ran.intValue()); }catch(InterruptedException e) {} if(!isTrue) System.out.println( Thread.currentThread().getName() + " - Oh, No!"); isTrue = !isTrue; } } }; t.start(); } } public static void main(String... args) { BooleanTest bt = new BooleanTest(); bt.aMethod(); } } When you run the above code, you will see "-Oh, No!" from time to time, indicating that different threads enter the synchronized code block at the same time.
2. It is thought that different objects are synchronized, but it is actually one object.
Sometimes we may want to synchronize on multiple objects. If Boolean is used as the synchronized object, it is likely that two synchronization blocks that should have no relationship use the same object lock. Examples are as follows:
Code 4:
private volatile Boolean aBoolean = Boolean.FALSE; private volatile Boolean anotherBoolean = false; public void aMethod() { ... synchronized(aBoolean) { //TODO: Access critical resource 1 } ... } public void anotherMethod() { . .. synchronized(anotherBoolean) { //TODO: Access critical resource 2 } ... } Assume that originally aMethod and anotherMethod will be called by two sets of unrelated threads. However, since Boolean.FALSE and false point to the same object, access to critical resource 2 may be blocked by critical resource 1 (and vice versa).
The above two situations indicate that when using synchronized blocks, try not to use Boolean objects as synchronized objects, otherwise unexpected problems may occur, or traps may be caused in future code modifications.
It can also be seen from this that any synchronization of constants is risky. If you must synchronize Boolean, you must use the new operator to create a Boolean object.