Jpa 为什么会出现僵局?
您好,我在JavaFX应用程序中遇到了死锁,我不知道为什么会发生这种情况。。。 初始化应用程序时,我启动一个线程来加载某个视图,该视图正在创建一个扩展DatabaseManager的对象。同时,另一个线程正在扩展DatabaseManager的另一个视图和另一个对象上执行相同的操作 进入以下构造函数的第一个线程进入同步块,但从未到达“System.out.println(“*****3”);”行。 发生这种情况后,我后来启动的线程进入构造函数,当然被阻塞了,因为资源再也没有被释放过。 通过线程1。 任何想法,为什么会导致僵局?我将javafx.concurrent.Task与java.lang.Thread一起使用Jpa 为什么会出现僵局?,jpa,javafx,deadlock,Jpa,Javafx,Deadlock,您好,我在JavaFX应用程序中遇到了死锁,我不知道为什么会发生这种情况。。。 初始化应用程序时,我启动一个线程来加载某个视图,该视图正在创建一个扩展DatabaseManager的对象。同时,另一个线程正在扩展DatabaseManager的另一个视图和另一个对象上执行相同的操作 进入以下构造函数的第一个线程进入同步块,但从未到达“System.out.println(“*****3”);”行。 发生这种情况后,我后来启动的线程进入构造函数,当然被阻塞了,因为资源再也没有被释放过。 通过线程1
public abstract class DatabaseManager {
protected static final AtomicReference<EntityManager> entityManager = new AtomicReference<>();
protected DatabaseManager() {
if (entityManager.get() == null) {
System.out.println("****1");
synchronized (entityManager) {
if (entityManager.get() == null) {
System.out.println("****2");
entityManager.set(Persistence.createEntityManagerFactory(
DatabaseConstants.hsqlPersistenceUnitName,
DatabaseConstants.getProperties()).createEntityManager());
System.out.println("****3");
}
}
}
}
...
公共抽象类数据库管理器{
受保护的静态最终AtomicReference entityManager=新的AtomicReference();
受保护的数据库管理器(){
if(entityManager.get()==null){
系统输出打印项次(“**1”);
已同步(entityManager){
if(entityManager.get()==null){
系统输出打印项次(“**2”);
set(Persistence.createEntityManagerFactory(
DatabaseConstants.hsqlPersistenceUnitName,
DatabaseConstants.getProperties()).createEntityManager();
系统输出打印项次(“**3”);
}
}
}
}
...
AtomicReference
s(以及他们的原始包装器朋友)管理自己的原子性。因此,虽然我真的不明白这是死锁的原因,但使用同步块来使用AtomicReference
首先破坏了AtomicReference
的全部目的
您只需执行以下操作:
protected DatabaseManager() {
entityManager.compareAndSet(null,
Persistence.createEntityManagerFactory(
DatabaseConstants.hsqlPersistenceUnitName,
DatabaseConstants.getProperties()).createEntityManager());
}
这将产生与您尝试执行的操作完全相同的效果(显然,没有日志记录)
惰性初始化静态字段的推荐方法是使用“惰性初始化持有者类习惯用法”:
这确保了延迟初始化,因为内部类DatabaseManager.EntityManager文件夹在第一次引用之前不会加载,而在getEntityManager()之前不会加载
是第一次调用。它是保证原子的,因为类初始值设定项是保证原子的。此外,由于原子性仅在内部类初始化时强制执行,因此后续调用getEntityManager()
时不会产生同步成本。(相比之下,使用AtomicReference
的解决方案在每次创建新的数据库管理器时执行对AtomicReference.compareAndSet(…)
的调用(可能是内部同步的)
请参阅Josh Bloch的有效Java,第71项,以获得更全面的讨论。我找到了死锁事件的解决方案,尽管我不知道为什么会导致死锁。。。
我只有另一个线程正在尝试访问另一个数据库。该应用程序与两个数据库交互。我的HSQL数据库上的所有性能都来自我的DatabaseManager,当一个线程试图初始化DatabaseManager中的EntityManager时,第三个线程只是在调用
Persistence.createEntityManagerFactory(DBConstants.ORACLE_PERSISTENCE_UNIT).createEntityManager();
删除该行并使用DatabaseManager建立到第二个数据库的连接后,死锁消失了。
但我不知道为什么。在我看来,唯一可能的解决办法是日食本身在那里陷入僵局
Persistence.createEntityManagerFactory(DBConstants.ORACLE_PERSISTENCE_UNIT).createEntityManager();