如果由于一个或多个线程通过可锁定资源创建循环的可能性而产生循环依赖关系,则只能看到死锁。
一种选择是通过仔细的静态分析或通过设计模式来获取锁来避免这些循环。
但是,我们可以通过在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();
}
}
答案 0 :(得分:1)
使用Lock.tryLock()
的代码是死锁安全的,但您应该尝试使用其他方法
public boolean tryLock(long timeout,
TimeUnit unit)
如果您的线程运行时间短。通话 - tryLock(0,TimeUnit.SECONDS)
优于Lock.tryLock()
,因为它尊重公平政策,即锁定等待队列得到尊重,而tryLock()
并不尊重。
即使静态分析告诉我们代码容易出现死锁,但是并不总是需要一个容易死锁的代码实际上会产生死锁,因为它的所有不幸的计时游戏所以你的目标tryLock()
应该产生功能上与使用死锁的代码相同的程序,假设不会发生死锁。
修复一个问题不应该引入其他问题,并且在你的代码中看起来很可能在一些不幸的时机,一个线程可能根本不执行所以我建议使用定时的trylock而不是强制trylock如果它的强制性锁定获取按顺序。
希望它有所帮助!!