简体   繁体   中英

Java synchronized and static synchronized method accessing static field

What would be the behaviour of the following program where static synchronized method and instance synchronized method is trying to access static field of same class in different threads? Will any thread get blocked? Its very confusing.

class MyClass
{
        public static int i = 5;

        public synchronized void m1()
        {
                System.out.println(i); //uses static field i of MyClass
            //T1 is executing this method
        }

        public static synchronized void m3()
        {
            //T2 will be able to call this method on same object lock while it is using
            //static field i???
            System.out.println(i);//uses static field i of MyClass
        }
}

Synchronized instance methods are equivalent of

public void m1() {
    synchronized(this) {
        ...
    }
}

(well, they are not exactly the same, but the answer to your question does not suffer from that difference).

Synchronized static methods are synchronized on the class:

public void m2() {
    synchronized(MyClass.class) {
        ...
    }
}

As you can see, two block are synchronized on difference objects: m1 is synchronized on the instance it is called on, and m2 is synchronized on the instance of Class<MyClass> which represents your class in JVM. So those two methods can be called without blocking each other.

You are always synchronizing on an object.

Funciton m1 synchronizes on an instance of an object on which it is called.

Function m3 synchronizes on the class itself.

m1 could be written as:

        public void m1()
        {
            synchronized(this) { 
                System.out.println(i); //uses static field i of MyClass
                //T1 is executing this method
            }
        }

Therefore you are synchronizing on two different objects and these two methods can acces any global variable concurrently.

The method m1 and m3 can be executed independently.

Because as you already said static synchronized is on the object. Therefore the same as synchronize(MyClass.class) .

synchronized are instance wide usable. So it is only blocked for the instances. It would be the same as using:

MyClass myClass = new MyClass();
synchronize (myClass)
{
.....
}

Your sample code looks good.

Best way to assure synchronization of static variables according to me is. As lock object is not accessible outside your Class. See below.

public class MyClass
{
    private static int i = 0;
    private static final Object lockObject = new Object();

    public void m1() {
        synchronized (lockObject ) {
            //Use you static var
        }
    }

    public void m3() {
        synchronized (lockObject ) {
            //Use you static var
        }
    }
} 

Java does not have any synchronization controls that relate to accessing static fields.

If you make your methods empty, the synchronization will be exactly the same.

Specifically, as long as any thread is executing any synchronized static method in that type, all other threads that call synchronized static methods will wait for them to finish, so that at most one synchronized static method will be executing at once.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM