The race condition happens, even if the calling code block is synchronised. On a second thought, it seems to be a lock issue. Please, check out the following simple code block (code will explain it better)-
class CriticalSectionTest {
public void initWithSync() {
final CriticalSection cSection = new CriticalSection();
Thread threadA = new Thread(new Runnable() {
@Override public void run() {
synchronized (cSection) {
cSection.add(2);
System.out.println(
"Value after adding from thread-A: " + cSection.getCount());
}
}
});
Thread threadB = new Thread(new Runnable() {
@Override public void run() {
synchronized (cSection) {
cSection.add(3);
System.out.println(
"Value after adding from thread-B: " + cSection.getCount());
}
}
});
threadA.start();
threadB.start();
//Desired output:
//A: 2
//B: 5
}
}
class CriticalSection {
private long count = 0;
public void add(long value) {
/* This method was not made synchronized, intentionally as its done in caller class
*/
this.count = this.count + value;
}
public long getCount() {
return count;
}
}
On multiple runs, it prints following outputs -
It's not ok
Value after adding from thread-B: 3
Value after adding from thread-A: 5
It looks ok
Value after adding from thread-A: 2
Value after adding from thread-B: 5
Any explanation? or am I missing some basics?
Synchronization doesn't determine order of execution. It just guarantees that the threads don't execute the code at the same time.
Calling Thread.start()
doesn't immediately call Thread.run()
; it just asks the thread scheduler to run it at some point in the future. The explanation for the behaviour you describe is that the thread scheduler might start executing thread B before the thread A sometimes. That is expected behaviour.
If you want the code to execute in a particular order and sequentially, it is much easier to do it all in a single thread.