Подтвердить что ты не робот

Java - синхронизация статических методов

Вот фрагмент текста, который я нашел в этой ссылке.

"Избегайте блокировки статических методов

Самое худшее решение - поставить" синхронизированные "ключевые слова на статическую методы, что означает, что он заблокирует все экземпляры этого класса."

Почему синхронизация статического метода блокирует все экземпляры класса? Разве он не должен просто блокировать класс?

4b9b3361

Ответ 1

Вот мой тестовый код, который показывает, что вы правы, и статья немного чрезмерно осторожна:

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();
        }
    }
}

Печать

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

Итак, static synchronized не имеет отношения к методам synchronized в экземплярах...

Конечно, если во всей системе используются методы static synchronised, то вы можете ожидать, что они окажут наибольшее влияние на пропускную способность многопоточных систем, поэтому используйте их на свой страх...

Ответ 2

Чтобы понять это, самый простой способ - сравнить, как блокировка работает против метода экземпляра и статического метода. Скажем, у вас есть класс Test.java, который имеет два метода:

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

   public synchronized static void staticMethod(){
   } 
}

Между тем есть два экземпляра класса Test, testA и testB. А также есть два потока tA и tB, пытающихся параллельно обращаться к классу Test.

блокировка на instanceMethod: Когда tA получает блокировку instanceMethod testA, tB не может получить доступ к тому же методу в testA, однако tB по-прежнему может вызывать instanceMethod в testB. Поскольку синхронизация с instanceMethod является блокировкой уровня экземпляра

блокировка на staticMethod: Однако, когда tA получает блокировку staticMethod, блокировка не имеет ничего общего с testA или testB, поскольку синхронизация по статическому методу - это блокировка уровня класса. Это означает, что tB вообще не может получить доступ к staticMethod, пока tA не освободит блокировку

Ответ 3

Фактически блокировка статического метода класса Foo аналогична установке блокировки на Foo.class (которая является единственным экземпляром):

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

Ответ 4

Вы правы. фактическая блокировка находится на самом экземпляре Class, а не на любом экземпляре класса (не говоря уже о всех экземплярах) — но я думаю, что вы интерпретируете связанную страницу слишком буквально. Он сам использует фразу "статический замок (блокировка класса)", поэтому его автор знает, как работает блокировка. Но если у вас много экземпляров в разных потоках, которые используют синхронные статические методы, тогда эти экземпляры будут блокировать друг друга. Синхронизированные статические методы не будут приводить к блокировке синхронных методов экземпляра, но проблема существует независимо.

Ответ 5

Он не говорит "блокировать все экземпляры класса". В нем говорится: "Блокировать все экземпляры класса. Это плохо сформулировано, правда неверно, но это не говорит, что вы сказали, что он сказал.

Ответ 6

Синхронизированный метод получает монитор (§17.1) перед его выполнением. Для класса (статического) метода используется монитор, связанный с объектом класса для класса метода. Для метода экземпляра используется связанный с ним монитор (объект, для которого был вызван метод).

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