Статические методы, синхронизированные с Java:блокировка объекта или класса

StackOverflow https://stackoverflow.com/questions/437620

Вопрос

В руководствах по Java говорится:"чередование двух вызовов синхронизированных методов для одного и того же объекта невозможно".

Что это означает для статического метода?Поскольку статический метод не имеет связанного объекта, будет ли ключевое слово synchronized блокировать класс, а не объект?

Это было полезно?

Решение

Поскольку статический метод не имеет связанного объекта, будет ли ключевое слово synchronized блокировать класс, а не объект?

ДА.:)

Другие советы

Просто для того, чтобы добавить немного деталей к ответу Оскара (приятно лаконично!), соответствующий раздел в спецификации языка Java: 8.4.3.6,« синхронизированные методы »:

  

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

Один момент, с которым вы должны быть осторожны (несколько программистов обычно попадают в эту ловушку), заключается в том, что нет связи между синхронизированными статическими методами и синхронизированными нестатическими методами, т.е.:

class A {
    static synchronized f() {...}
    synchronized g() {...}
}

Главная:

A a = new A();

Резьба 1:

A.f();

Поток 2:

a.g();

f() и g() не синхронизированы друг с другом и, следовательно, могут выполняться полностью одновременно.

Если вы не реализуете g () следующим образом:

g() {
    synchronized(getClass()) {
        ...
    }
}

Я считаю этот шаблон полезным, когда я хочу реализовать взаимное исключение между различными экземплярами объекта (например, это необходимо при доступе к внешнему ресурсу).

Статический метод также имеет связанный объект. Он принадлежит файлу Class.class в наборе инструментов JDK. Когда файл .class загружается в оперативную память, Class.class создает экземпляр этого объекта, который называется шаблоном.

Например: - когда вы пытаетесь создать объект из существующего класса клиента, например

Customer c = new Customer();

Класс Customer.class загружается в оперативную память. В этот момент Class.class в JDK toolkit создает объект с именем Template и загружает этот Customer.class в этот объект шаблона. Статические члены этого Customer.class становятся атрибутами и методами в этом объекте шаблона.

Поэтому у статического метода или атрибута также есть объект

Приведенные ниже примеры дают больше ясности между блокировкой классов и объектов, надеюсь, что приведенный ниже пример поможет и другим:)

Например, у нас есть следующие методы: один метод получения класса, а другой захват объекта:

public class MultiThread {

    public static synchronized void staticLock() throws InterruptedException {
        for (int i = 0; i < 10; i++) {
            Thread.sleep(100);
            System.out.println(Thread.currentThread().getName() + " " + i);
        }
    }

    public synchronized void objLock() throws InterruptedException {
        for (int i = 0; i < 10; i++) {
            Thread.sleep(100);
            System.out.println(Thread.currentThread().getName() + " " + i);
        }
    }
}

Итак, теперь у нас могут быть следующие сценарии:

<Ол>
  • Когда потоки, использующие один и тот же объект , пытаются получить доступ к методу objLock ИЛИ staticLock одновременно (т. е. оба потока пытаются получить доступ к одному и тому же методу)

    Thread-0 0
    Thread-0 1
    Thread-0 2
    Thread-0 3
    Thread-0 4
    Thread-1 0
    Thread-1 1
    Thread-1 2
    Thread-1 3
    Thread-1 4
    
  • Когда потоки, использующие один и тот же объект , пытаются получить доступ к методам staticLock и objLock одновременно (пытается получить доступ к различным методам)

    Thread-0 0
    Thread-1 0
    Thread-0 1
    Thread-1 1
    Thread-0 2
    Thread-1 2
    Thread-1 3
    Thread-0 3
    Thread-0 4
    Thread-1 4
    
  • Когда потоки, использующие другой объект , пытаются получить доступ к методу staticLock

    <*>
  • Когда потоки, использующие другой объект , пытаются получить доступ к методу objLock

    <*>
  • Для тех, кто не знаком, статический синхронизированный метод заблокирован на объекте класса, например. для строкового класса его String.class, в то время как метод синхронизации экземпляров блокирует текущий экземпляр объекта, обозначенный в Java ключевым словом this. Поскольку оба эти объекта различны, они имеют разную блокировку, поэтому, пока один поток выполняет статический синхронизированный метод, другому потоку в java не нужно ждать возврата этого потока, вместо этого он получит отдельную блокировку, обозначенную байтом .class, и войдет в статический синхронизированный метод.

    scroll top