Синхронизированные статические методы Java: блокировка объекта или класса - PullRequest
143 голосов
/ 13 января 2009

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

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

Ответы [ 8 ]

197 голосов
/ 13 января 2009

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

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

125 голосов
/ 13 января 2009

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

Да. :)

79 голосов
/ 13 января 2009

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

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

Main:

A a = new A();

Тема 1:

A.f();

Тема 2:

a.g();

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

13 голосов
/ 06 февраля 2010

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

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

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

4 голосов
/ 01 ноября 2016

Взгляните на страницу документации оракула на Внутренние блокировки и синхронизация

Вы можете задаться вопросом, что происходит, когда вызывается статический синхронизированный метод, поскольку статический метод связан с классом, а не объектом. В этом случае поток получает внутреннюю блокировку для объекта Class, связанного с классом . Таким образом, доступ к статическим полям класса контролируется блокировкой, отличной от блокировки для любого экземпляра класса .

2 голосов
/ 13 августа 2017

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

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

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

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

  1. Когда потоки, использующие один и тот же Объект , пытаются получить доступ к методу 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
    
  2. Когда потоки, использующие тот же объект , пытаются получить доступ к 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
    
  3. Когда потоки, использующие другой объект , пытаются получить доступ 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
    
  4. Когда потоки, использующие другой объект , пытаются получить доступ к objLock method

    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
    
2 голосов
/ 09 ноября 2016

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

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

Customer c = new Customer();

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

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

0 голосов
/ 24 мая 2017

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...