something strange happen with synchronized (Test2.class)

62 Views Asked by At
public class Test2 {
    static int count;
    public static void main(String[] args) {
        final Test2 t1 = new Test2();
        final Test2 t2 = new Test2();

        new Thread(new Runnable() {

            @Override
            public void run() {
                t1.foo();
            }
        }).start();

        new Thread(new Runnable() {

            @Override
            public void run() {
                t1.bar();
            }
        }).start();

        new Thread(new Runnable() {

            @Override
            public void run() {
                t2.foo();
            }
        }).start();
    }
    public static synchronized void foo() {
        synchronized (Test2.class) {
            System.out.println("run bar"+count++);
            try {
                Thread.sleep(100000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
    public static synchronized void bar() {
        System.out.println("run bar");
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

above are codes which I tried.When I write all codes in one Class synchronized (Test2.class) and I found something strange happened.After I invoked foo() method I can't invoke bar() method immediately. what I think it lock same object.how to explain this strange thing.

1

There are 1 best solutions below

0
On

All 3 of the threads your code starts acquire the same lock, on the Test2 class. When you write a method starting with

static synchronized

that means it has to acquire the lock on the class object.

The synchronized block in the foo method is redundant. It specifies using the same class to lock on as using static synchronized. Since intrinsic locks are reentrant this doesn't cause a problem.

Anyway, each of your threads acquires the lock, runs to completion, then releases the lock. Since you are locking on the class and not on an instance it doesn't matter which instance of Test2 your threads use, they still acquire the same lock and execute one at a time.

When I ran this I got the following output:

c:\Users\ndh>java Test2
run bar0
run bar1
run bar

The order in which these threads run is up to the scheduler. It would seem reasonable to guess that the Runnable calling t1.foo got a head start -- since it was created and started first it's likely to have a window where it won't have any competition acquiring the lock.