Java 为什么下面的代码会导致死锁
我有以下课程Java 为什么下面的代码会导致死锁,java,multithreading,locking,Java,Multithreading,Locking,我有以下课程 public class LockTester implements Runnable{ private static Locker locker = new Locker(); public static void main(String[] args){ for(int i=0;i<10;i++){ Thread t = new Thread(new LockTester()); t.start(); } } public void run
public class LockTester implements Runnable{
private static Locker locker = new Locker();
public static void main(String[] args){
for(int i=0;i<10;i++){
Thread t = new Thread(new LockTester());
t.start();
}
}
public void run(){
for(int i=0;i<1000;i++){
locker.unlockFirst();//note unlocking here
locker.lockFirst();
locker.lockSecond();
locker.unlockSecond();
locker.unlockFirst();
}
}
}
为什么运行此代码会导致死锁 您有一个跨所有线程共享的静态锁 在某个时刻,当锁已经被另一个线程持有时,一个线程将尝试tryLock()
编辑:不正确,忽略。锁定了
lock1
,您永远无法完全解锁它。如果线程在调用unlockFirst()
时保持lock1
,那么当函数返回时,它仍然保持lock1
如果调用
lock1.lock()
,然后成功调用lock1.tryLock()
,则需要调用lock1.unlock()
两次才能完全释放锁。您的代码没有这样做,因此会出现死锁。lock1被锁定两次:一次在lockFirst
中,另一次在unlockFirst
(lock1.tryLock()
)中,但在unlockFirst
中仅解锁一次
ReentrantLock有一个保持计数。看见如果调用tryLock,即使当前线程已经持有它,它仍然会增加持有计数。所以,增加两次,但只减少一次。如果移除第一次解锁,它仍然死锁吗?那又怎样?tryLock就是为了处理这个问题而设计的。所以我必须解锁它两次吗?只需移除if(lock1.tryLock)和对unlockFirst的第一个调用。你需要它吗?Upvote for“被锁定两次”。unlockFirst()方法中的tryLock()肯定是问题所在。@Tudor:那么有没有办法通过当前线程解锁所有锁,或者需要多次调用unlock方法(注:我不需要lock.tryLock,但正在尝试一些场景)锁的第1条和第2条规则是:如果你有多个嵌套锁,总是按照与锁定相反的顺序解锁,并且总是锁定和解锁相同的次数。所以嵌套锁1 lock2 unlock2 unlock1是您需要的。这并不完全正确。他确实解锁了,只是次数不够。
public class Locker{
private Lock lock1 = new ReentrantLock();
private Lock lock2 = new ReentrantLock();
public void lockFirst(){
lock1.lock();
}
public void lockSecond(){
lock2.lock();
}
public void unlockFirst(){
if(lock1.tryLock()){//note change
lock1.unlock();
}
}
public void unlockSecond(){
lock2.unlock();
}
}