Если у меня есть класс 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
}
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.
Таким образом, если один поток входит в статический метод, тот же объект, возвращенный Object # getClass , блокируется. Другие потоки все еще могут обращаться к методам экземпляра.Class
объект, созданный одним из загрузчиков классов виртуальных машин. Как и все объекты, этот объект тожеMonitor
связан с ним. И этот монитор - то, что заблокировано.Для решения вопроса в более общем плане ...
Имейте в виду, что использование синхронизированных методов на самом деле является просто сокращением (предположим, что класс это SomeClass):
такой же как
и
такой же как
Вы можете использовать любой объект в качестве замка. Если вы хотите заблокировать подмножества статических методов, вы можете
(для нестатических методов вы бы хотели, чтобы блокировки были нестатическими полями)
источник
Статические методы используют класс в качестве объекта для блокировки, который для вашего примера является Utils.class. Так что да, все в порядке.
источник
static synchronized
означает удержание блокировки наClass
объекте класса, где assynchronized
означает удержание блокировки на самом объекте этого класса. Это означает, что если вы обращаетесь к нестатическому синхронизированному методу в потоке (выполнения), вы все равно можете получить доступ к статическому синхронизированному методу, используя другой поток.Таким образом, доступ к двум одинаковым методам (двум статическим или двум нестатическим методам) в любой момент времени более чем одним потоком невозможен.
источник
Почему вы хотите обеспечить, чтобы только один поток мог одновременно обращаться к БД?
Задача драйвера базы данных - реализовать любую необходимую блокировку, предполагая, что a
Connection
используется только одним потоком за раз!Скорее всего, ваша база данных вполне способна обрабатывать множественный параллельный доступ
источник
Если это связано с данными в вашей базе данных, почему бы не использовать блокировку изоляции базы данных для достижения этой цели?
источник
Чтобы ответить на ваш вопрос, да, это так: ваш
synchronized
метод не может быть выполнен более чем одним потоком одновременно.источник
Как
synchronized
работает ключевое слово JavaКогда вы добавляете
synchronized
ключевое слово в статический метод, метод может вызываться только одним потоком за раз.В вашем случае каждый вызов метода будет:
SessionFactory
Session
Тем не менее, это были ваши требования:
getObjectById
вызова для всех классов, когда он вызывается определенным классомТак что, даже если
getObjectById
метод является поточно-ориентированным, реализация ошибочна.SessionFactory
лучшие практикиSessionFactory
Потокобезопасно, и это очень дорогой объект для создания , как это необходимо для анализа классов сущностей и построить внутреннее представление сущности метамодели.Таким образом, вы не должны создавать
SessionFactory
на каждомgetObjectById
вызов метода.Вместо этого вы должны создать для него одноэлементный экземпляр.
Session
Всегда должен быть закрытВы не закрыли
Session
вfinally
блоке, и это может привести к утечке ресурсов базы данных , если исключение при загрузке сущности.Согласно
Session.load
методу JavaDoc может выдать ,HibernateException
если объект не может быть найден в базе данных.Вот почему вам нужно использовать
finally
блок, чтобы закрытьSession
, как это:Предотвращение многопоточного доступа
В вашем случае вы хотели убедиться, что только один поток получает доступ к этой конкретной сущности.
Но
synchronized
ключевое слово не позволяет двум потокам вызыватьgetObjectById
одновременный . Если два потока вызывают этот метод один за другим, у вас все равно будет два потока, использующих этот объект.Итак, если вы хотите заблокировать данный объект базы данных, чтобы никакой другой поток не мог изменить его, вам нужно использовать блокировки базы данных.
synchronized
Ключевое слово работает только в одной виртуальной машине Java. Если у вас есть несколько веб-узлов, это не помешает многопоточному доступу через несколько JVM.Что вам нужно сделать, это использовать
LockModeType.PESSIMISTIC_READ
илиLockModeType.PESSIMISTIC_WRITE
при внесении изменений в БД, например так:Итак, вот что я сделал:
EntityTransaction
и начал новую транзакцию базы данныхPost
объект, удерживая блокировку связанной записи базы данныхPost
сущность и совершил транзакциюException
выбрасывания я откатил транзакциюисточник