sotn
sotn

Reputation: 2101

Java - synchronizing static methods

Here is a piece of text I found at this link.

"Avoid lock on static methods

The worst solution is to put the "synchronized" keywords on the static methods, which means it will lock on all instances of this class."

Why would synchronizing a static method lock all instances of the class? Shouldn't it just lock the Class?

Upvotes: 12

Views: 24982

Answers (6)

Robert Christian
Robert Christian

Reputation: 18310

A synchronized method acquires a monitor (§17.1) before it executes. For a class (static) method, the monitor associated with the Class object for the method's class is used. For an instance method, the monitor associated with this (the object for which the method was invoked) is used.

http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.4.3.6

Upvotes: 2

user207421
user207421

Reputation: 310936

It doesn't say 'lock all instances of the class'. It says 'lock on all instances of the class. It's poorly worded, indeed incorrect, but it doesn't it say what you said it said.

Upvotes: 2

beny23
beny23

Reputation: 35018

Here's my test code that shows that you're right and the article is a bit over-cautious:

class Y {
    static synchronized void staticSleep() {
        System.out.println("Start static sleep");
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
        }
        System.out.println("End static sleep");
    }

    synchronized void instanceSleep() {
        System.out.println("Start instance sleep");
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
        }
        System.out.println("End instance sleep");
    }
}

public class X {
    public static void main(String[] args) {
        for (int i = 0; i < 2; ++i) {
            new Thread(new Runnable() {

                public void run() {
                    Y.staticSleep();
                }
            }).start();
        }

        for (int i = 0; i < 10; ++i) {
            new Thread(new Runnable() {

                public void run() {
                    new Y().instanceSleep();
                }
            }).start();
        }
    }
}

Prints:

Start instance sleep
Start instance sleep
Start instance sleep
Start instance sleep
Start instance sleep
Start static sleep
Start instance sleep
Start instance sleep
Start instance sleep
Start instance sleep
Start instance sleep
End instance sleep
End instance sleep
End instance sleep
End instance sleep
End instance sleep
End instance sleep
End instance sleep
End instance sleep
End instance sleep
End instance sleep
End static sleep
Start static sleep
End static sleep

So the static synchronized has no bearing on the synchronized methods on the instances...

Of course if static synchronised methods are used throughout the system, then you can expect them to have the most impact on the throughput of a multithreaded systems, so use them at your peril...

Upvotes: 7

spiritwalker
spiritwalker

Reputation: 2257

To understand this, the easiest way is to compare how lock works against instance method and static method. Let's say you have class Test.java, which has two methods as follow.

public class Test{
   public synchronized void instanceMethod(){
   }

   public synchronized static void staticMethod(){
   } 
}

Meanwhile, there are two instances of class Test, testA and testB. And also there are two thread tA and tB trying to access class Test in parallel.

locking on instanceMethod: When tA gets the lock on instanceMethod of testA, tB cannot access the the same method in testA, however tB is still free to invoke instanceMethod in testB. Because the synchronization against instanceMethod is instance level locking

locking on staticMethod: However, when tA gets the lock on staticMethod, the lock has nothing to do with testA or testB, since synchronization on static method is a class level locking. Which means tB cannot access staticMethod at all until tA release the lock

Upvotes: 35

ruakh
ruakh

Reputation: 183361

You are right — the actual lock is on the Class instance itself, not on any instance of the class (let alone all instances) — but I think you're interpreting the linked page too literally. It itself uses the phrase "a static lock (a Class lock)", so clearly its author is aware of how the locking works. But if you have many instances in different threads that are all using synchronized static methods, then those instances will all lock each other out. The synchronized static methods won't cause blocking of synchronized instance methods, but the problem is there regardless.

Upvotes: 4

Eng.Fouad
Eng.Fouad

Reputation: 117597

Actually a lock on a static method of class Foo, is the same as putting a lock on Foo.class (which is the only instance):

public static void doSomething()
{
    synchronized(Foo.class)
    {
        // ...
    }
}

Upvotes: 8

Related Questions