Вопрос

Будет ли использование ключевого слова 'synchronized' в методах в Java DAO вызывать проблемы при использовании веб-приложением?

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

java.util.concurrent.ExecutionException: javax.persistence.PersistenceException: org.hibernate.HibernateException: Found shared references to a collection: com.replaced.orm.jpa.Entity.stuffCollection

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

Я использую внедренную Spring фабрику JPA entity manager factory, которая предоставляет entity manager DAO.Технически я мог бы удалить слой DAO и заставить классы напрямую вызывать фабрику entity manager, но мне нравится разделение, предоставляемое DAO.

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

В этом случае использование DAO принесет больше вреда, чем поможет?


Большая часть информации, о которой я умолчал, заключается в том, что DAO не является синглтоном.Если бы я мыслил достаточно здраво, чтобы включить эту деталь, я, вероятно, вообще не задал бы этот вопрос.

Если я правильно понимаю, Spring создает новый экземпляр класса DAO для каждого класса, который его использует.Таким образом, менеджер резервных сущностей должен быть уникальным для каждого потока.Отказ от совместного использования entity manager, как ответил Роб Х., является ключевым моментом здесь.

Однако теперь я не понимаю, почему я получаю ошибки при удалении synchronized .


В соответствии с этим Нитки, аннотация @PersistenceContext создает потокобезопасный SharedEntityManager.Таким образом, вы должны быть в состоянии создать одноэлементный DAO.

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

Решение

Вы говорите, что не разделяете объекты entity между потоками.Это хорошо.Но вы также должны убедиться, что вы не делитесь EntityManager ( Менеджер объектов ) объекты (или Сессия объекты в режиме гибернации) либо в разных потоках.Фреймворки, такие как Spring, управляют этим за вас автоматически, сохраняя сеанс в локальной переменной потока.Если вы кодируете свои собственные DAO без помощи фреймворка, вам необходимо самостоятельно принять меры предосторожности, чтобы избежать их совместного использования.

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

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

Если это необходимо синхронизировать для обеспечения потокобезопасности, то оставьте их там.В этом случае блокировка требуется в любом случае.Если блокировка не требуется для случая веб-приложения, вы можете либо:

  • оставьте все как есть, поскольку производительность снижается, когда нет разногласий по блокировка незначительна и незначительна, если принять во внимание затраты на доступ к базе данных.
  • Измените его таким образом, чтобы добавить уровень синхронизации для автономного варианта приложения, который защищает базовый несинхронизированный DAO.

Лично я бы оставил все как есть и профилировал, чтобы узнать, нужен ли вам рефакторинг.До тех пор вы просто проводите преждевременную оптимизацию.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top