Concurrency in Java using synchronized blocks not giving expected results Concurrency in Java using synchronized blocks not giving expected results multithreading multithreading

Concurrency in Java using synchronized blocks not giving expected results


Ok let's have a look at the different possibilities you mention:

1.

for (int ii=0; ii<NUM_EVENTS; ++ii) {  synchronized( monitor) {    synchronized(cnt) {        // <-- is this synchronized necessary?      monitor.add(cnt);    }    synchronized(cnt) {      cnt++;        // <-- why does moving the synchronized block to here result in the correct value for cnt?    }}

First the monitor object is shared between the threads, therefore getting a lock on it (that is what synchronized does) will make sure that the code inside of the block will only be executed by one thread at a time. So the 2 synchronized inside of the outer one are not necessary, the code is protected anyway.

2.

for (int ii=0; ii<NUM_EVENTS; ++ii) {  synchronized( monitor) {    monitor.add(cnt);  }  synchronized(cnt) {    cnt++;              // <-- why does moving the synchronized block here result in cnt being wrong?  }}

Ok this one is a little bit tricky. cnt is an Integer object and Java does not allow modifying an Integer object (Integers are immutable) even though the code suggests that this is what is happening here. But what acutally will happen is that cnt++ will create a new Integer with the value cnt + 1 and override cnt.This is what the code actually does:

synchronized(cnt) {  Integer tmp = new Integer(cnt + 1);  cnt = tmp;}

The problem is that while one thread will create a new cnt object while all other threads are waiting to get a lock on the old one. The thread now releases the old cnt and will then try to get a lock on the new cnt object and get it while another thread gets a lock on the old cnt object. Suddenly 2 threads are in the critical section, executing the same code and causing a race condition. This is where the wrong results come from.

If you remove the first synchronized block (the one with monitor), then your result gets even more wrong because the chances of a race increase.

In general you should try to use synchronized only on final variables to prevent this from happening.