Как синхронизированные статические методы работают на Java?

Если у меня есть класс util со статическими методами, которые вызовут функции Hibernate для выполнения базового доступа к данным. Мне интересно, является ли метод synchronized правильным методом обеспечения безопасности потоков.

Я хочу, чтобы это предотвращало доступ информации к тому же экземпляру БД. Тем не менее, теперь я уверен, что следующий код предотвращает вызов getObjectById для всех классов, когда он вызывается конкретным классом.

public class Utils {
     public static synchronized Object getObjectById (Class objclass, Long id) {
           // call hibernate class
         Session session = new Configuration().configure().buildSessionFactory().openSession();
         Object obj = session.load(objclass, id);
         session.close();
         return obj;
     }

     // other static methods
}

Ответ 1

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

Итак, ваше предположение верно.

Мне интересно, правильно ли синхронизирован метод - это правильный подход для обеспечения безопасности потоков.

Не совсем. Вы должны позволить этой работе выполнять свою RDBMS. Они хороши в этом.

Единственное, что вы получите, синхронизируя доступ к базе данных, - сделать ваше приложение ужасно медленным. Более того, в коде, который вы опубликовали, вы каждый раз создаете сеанс Factory, таким образом ваше приложение будет тратить больше времени на доступ к БД, чем выполнение фактического задания.

Представьте себе следующий сценарий:

Клиент A и B пытается вставить различную информацию в запись X таблицы T.

При вашем подходе единственное, что вы получаете, это удостовериться, что вызов вызван за другим, когда это произойдет в любом случае в БД, поскольку РСУБД не позволит им вставить половину информации из А и половины из В в в то же время. Результат будет таким же, но только в 5 раз (или более) медленнее.

Возможно, было бы лучше взглянуть на главу "Транзакции и Concurrency" в документации Hibernate. В большинстве случаев проблемы, которые вы пытаетесь решить, были решены уже и намного лучше.

Ответ 2

Чтобы решить вопрос в целом...

Имейте в виду, что использование синхронных методов очень просто (предположим, что класс - SomeClass):

synchronized static void foo() {
    ...
}

совпадает с

static void foo() {
    synchronized(SomeClass.class) {
        ...
    }
}

и

synchronized void foo() {
    ...
}

совпадает с

void foo() {
    synchronized(this) {
        ...
    }
}

Вы можете использовать любой объект в качестве блокировки. Если вы хотите заблокировать подмножества статических методов, вы можете

class SomeClass {
    private static final Object LOCK_1 = new Object() {};
    private static final Object LOCK_2 = new Object() {};
    static void foo() {
        synchronized(LOCK_1) {...}
    }
    static void fee() {
        synchronized(LOCK_1) {...}
    }
    static void fie() {
        synchronized(LOCK_2) {...}
    }
    static void fo() {
        synchronized(LOCK_2) {...}
    }
}

(для нестатических методов вы хотите, чтобы блокировки были нестатическими полями)

Ответ 3

Статические методы используют класс как объект для блокировки, который является Utils.class для вашего примера. Так что да, все в порядке.

Ответ 4

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

Таким образом, доступ к двум одинаковым методам (либо двум статическим, либо двум нестационарным методам) в любой момент времени более чем через поток невозможен.

Ответ 5

Почему вы хотите обеспечить, чтобы только один поток мог обращаться к БД в любой момент?

Это задача драйвера базы данных для реализации любой необходимой блокировки, если Connection используется только одним потоком за раз!

Скорее всего, ваша база данных идеально подходит для обработки нескольких параллельных доступов

Ответ 6

Если это что-то связано с данными в вашей базе данных, почему бы не использовать блокировку изоляции базы данных для достижения?

Ответ 7

Чтобы ответить на ваш вопрос, да, это так: ваш метод synchronized не может выполняться более чем одним потоком за раз.