Search code examples
javamultithreadingrace-condition

Java thread: Race condition vs synchronization


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?


Solution

  • 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.