user1050619
user1050619

Reputation: 20856

Java thread synchronization on methods

I'm trying to run a sample thread module using method Synchronization but the results are not as expected.

Since I have synchronized m1(), I would expect thread-1 completely print the values 0...10 and then thread-2 start running.

But, in this case the numbers are printed alternatively...

package threadexample;

public class Test implements  Runnable{
    public void run(){
        m1();
    }
    public synchronized void m1(){
        for (int i = 0; i < 10; i ++){
            System.out.println(Thread.currentThread().getName() + " Value of i = " + i);
        }
    }
    Test(String threadname){
        super();
    }

    public static void main(String[] args){
            Test a = new Test("A");
            Test b = new Test("B");
            Thread t1 = new Thread(a);
            Thread t2 = new Thread(b);
            t1.start();
            t2.start();

    }   

}



Output:

Thread-0 Value of i = 0
Thread-1 Value of i = 0
Thread-0 Value of i = 1
Thread-1 Value of i = 1
Thread-0 Value of i = 2
Thread-1 Value of i = 2
Thread-0 Value of i = 3
Thread-1 Value of i = 3
Thread-0 Value of i = 4
Thread-1 Value of i = 4
Thread-0 Value of i = 5
Thread-1 Value of i = 5
Thread-0 Value of i = 6
Thread-1 Value of i = 6
Thread-0 Value of i = 7
Thread-1 Value of i = 7
Thread-0 Value of i = 8
Thread-1 Value of i = 8
Thread-0 Value of i = 9
Thread-1 Value of i = 9

Upvotes: 1

Views: 82

Answers (2)

Avi
Avi

Reputation: 21858

The problem with synchronized on a method is that it locks on this. In your case you have 2 different instances - each of them has a different this reference. Using the synchronized word on a method is the same as doing this:

public void m1() {
    synchronized(this) {
        // Critical code section here
    }
}

If you want to do the lock you described your code should look like this:

public class Test implements  Runnable{

    private final static Object lock = new Object();

    public void run(){
        m1();
    }

    public void m1(){
        synchronized(lock) {
           for (int i = 0; i < 10; i ++){
               System.out.println(Thread.currentThread().getName() + " Value of i = " + i);
           }
        }
    }

   Test(String threadname){
        super();
   }

   public static void main(String[] args){
        Test a = new Test("A");
        Test b = new Test("B");
        Thread t1 = new Thread(a);
        Thread t2 = new Thread(b);
        t1.start();
        t2.start();

   }   

}

In this case you share the lock between the 2 instances (because it's static) and this way you lock on the same object and have your synchronization the way you wanted it to be.

Upvotes: 1

Sotirios Delimanolis
Sotirios Delimanolis

Reputation: 279960

You've synchronized an instance method. It will synchronize on the instance itself. However each of your Threads is using a different instance, ie. they are each synchronized on a different object and therefore not blocking each other.

You need to share your Test instance

Test a = new Test("A");
Thread t1 = new Thread(a);
Thread t2 = new Thread(a);

or use synchronized on a different shared object. You can do this either by passing a lock object as a constructor argument or using a static field reference.

Upvotes: 3

Related Questions