Balu
Balu

Reputation: 126

Synchronization Block

I am new to threads in Java and hence have this doubt. I read that a 'synchronized non-static method block' allows only one thread to enter the block (for one instance of non-static block, of-course). However it doesn't seem to work. Am I missing something? Look at the following code.

class A extends Thread
{
    public void run() 
    {
        B.b.add();
    }
}

class B
{
    static B b=new B();
    int i;
    public synchronized void add()
    {
        i++;
    }
}

public class Sample
{
    public static void main(String[] args) 
    {
        for(int i=0;i<10;i++)
        {
            new A().start();
        }
        System.out.println(B.b.i);
    }
}

Upvotes: 1

Views: 60

Answers (1)

Nathan Hughes
Nathan Hughes

Reputation: 96385

One problem here is that your main thread doesn't wait for the other threads to finish before it tries to retrieve the result. Using Thread#join works if you want to wait for a single thread, but here we want to wait for all 10. Modifying the program to use CountDownLatch makes the main thread wait until all the threads it created are finished.

Another problem is that the updated value of i isn't guaranteed to be visible. JVM implementations differ about how aggressively they perform optimizations (like delaying refreshes of cached values, or reordering bytecode) that may make the changes to i not visible to the main thread. Adding a synchronized method on the same lock as the add method to fetch the value of i fixes the visibility issue.

import java.util.concurrent.CountDownLatch;

class A extends Thread {
    private CountDownLatch latch;
    public A(CountDownLatch latch) {
        this.latch = latch;
    }    
    @Override public void run() {
        B.b.add();
        latch.countDown();
    }
}

class B {
    static B b=new B();
    int i;
    public synchronized void add() {
        i++;
    }
    public synchronized int getI() { 
        return i;
    }
}

public class Sample {
    public static void main(String[] args) throws Exception {
        CountDownLatch latch = new CountDownLatch(10);
        for(int i=0;i<10;i++) {
            new A(latch).start();
        }
        latch.await();     
        System.out.println(B.b.getI());
    }
}

Upvotes: 2

Related Questions