仅当存在一个或多个线程通过可锁定资源创建循环的可能性而产生周期性依赖关系时,死锁才可能出现。
一种选择是通过仔细的静态分析或通过获取锁的设计模式来避免这些周期。
但是,我们可以通过在Lock接口上使用tryLock来防止死锁吗?
tryLock尝试自动获取该锁,如果成功则返回true,如果已经锁定则返回false,因此我们可以跳过代码。
int sharedStateA = 0;
int sharedStateB = 0;
Lock lockA = new ReentrantLock();
Lock lockB = new ReentrantLock();
// possible deadlock safe solution
// executed by thread 1
void deadLockSafeUpdateAthenB(){
try {
if (lockA.tryLock()){
sharedStateA = sharedStateA + 1;
try {
if (lockB.tryLock()){
sharedStateB = sharedStateB + 1;
}
} finally {
lockB.unlock();
}
}
} finally {
lockA.unlock();
}
}
// executed by thread 2
void deadLockSafeUpdateBthenA(){
try {
if (lockB.tryLock()){
sharedStateB = sharedStateB + 1;
try {
if (lockA.tryLock()){
sharedStateA = sharedStateA + 1;
}
} finally {
lockA.unlock();
}
}
} finally {
lockB.unlock();
}
}
最佳答案
使用Lock.tryLock()
的代码是死锁安全的,但是您应该尝试使用其他方法,
public boolean tryLock(long timeout,
TimeUnit unit)
如果您的线程运行时间短。呼叫-
tryLock(0,TimeUnit.SECONDS)
比Lock.tryLock()
更好,因为它遵守公平性策略,即遵守锁等待队列而tryLock()
不遵守。即使静态分析告诉我们代码容易死锁,但并非总是必须这样,因为容易死机的代码都是不幸的计时游戏,因此,使用
tryLock()
的目标应该是在功能上与使用容易发生死锁的代码,假设不会发生死锁。解决一个问题不应引起其他问题,并且在您的代码中,很可能在某个不幸的时刻,一个线程可能根本无法执行,因此,如果要强制获取锁,则建议使用定时trylock而不是插入trylock那个命令。
希望能帮助到你 !!
关于java - 可以始终在Java Lock上使用tryLock来防止死锁吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/41733432/