2012-10-05 45 views
2

我使用单例记录在系统中同时发生的所有事件。带锁的单身人士 - 可能的死锁?在java

public class Singleton { 
    private static Lock dbLock; 
    protected Singleton() {} 
    private static class SingletonHolder { 
     private final static Singleton instance = new Singleton(); 
    } 
    public static Singleton getInstance() { 
     return SingletonHolder.instance; 
    } 
    public void recordEvent(Event ev) { 
     dbLock.lock(); 
    try { 
      database.insert(ev); 
     } finally { 
     dbLock.unlock(); 
    } 
    } 
    public File lockAndGetDB() { 
     dbLock.lock(); 
     return database.getFile(); 
    } 
    public void unlockDB() { 
     dbLock.unlock(); 
    } 
} 

每隔几个小时,我想锁定录制事件以通过互联网发送数据库。

file = Singleton.getInstance().lockAndGetDB(); 
try { 
    sendViaHTTP(file); 
} 
finally { 
    Singleton.getInstance().unlock(); 
} 

有没有可能的死锁?线程安全吗?

EDITED。 (尝试/最后添加通过HTTP发送)但这不是主要问题。问题是,如果有线程在等待dbLock.lock();在recordEvent(Event ev)是我的Singleton.getInstance()。unlock();将能够输入getInstance()代码并解锁?

+1

像这样实现一个锁定会对这个应用程序的性能产生巨大的影响......是否有任何理由不想使用JDBC? –

+0

@JordanDenison我正在Android中实现它。但它是关于java的一般问题 –

回答

1

更可能的是,可能会出现死锁。如果在database.getFilesendViaHTTP期间发生错误会发生什么情况?没有try/finally模式来确保调用Lock.unlock

+0

这是个例子的错误,我试图让它更简单。是的,当然,当我通过HTTP发送时,尝试/最后。但这不是重点。 –

+1

不可能获取Lock,也不能执行database.getFile。对于您当前的实现,也许该操作永远不会失败。不过,它发生在'lock'和'try'之间,所以我想像FindBugs这样的代码分析器会正确地投诉。 –

0

当您以不同的顺序获取锁时会出现死锁。由于这里只有一个实际的锁,所以这个问题不会出现。

您的案例看起来更像是一个读写锁定的候选人:使用读锁来允许DBMS操作的最大并发性,以及当您希望它们停止并发送文件时写锁定。

+0

@downvoter请解释。无法解释的downvotes实际上只是网站破坏行为。他们无人帮助。 – EJP

+0

获取锁定但从未释放时也会出现死锁。你所描述的只是一种形式的僵局。 –

+0

@TimBender不,这不是一个僵局。这只是一个锁。死锁是一个循环的过程链,每个链都拥有下一个想要的资源。 – EJP