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();
 }
}