为什么以下代码导致死锁

时间:2011-11-16 11:24:44

标签: 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(){
   for(int i=0;i<1000;i++){
    locker.unlockFirst();//note unlocking here
    locker.lockFirst();
    locker.lockSecond();
    locker.unlockSecond();
    locker.unlockFirst();
  }
 }
}

和Locker类

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

为什么运行此代码会导致死锁。

3 个答案:

答案 0 :(得分:9)

lock1被锁定两次:一次在lockFirst,一次在unlockFirstlock1.tryLock()),但只在unlockFirst解锁一次。

ReentrantLock有暂停计数。见ReentrantLock。如果你调用tryLock,即使它已经被当前线程保持,它仍然会增加保持计数。所以,你将它递增两次,但只递减一次。

答案 1 :(得分:2)

锁定lock1后,您永远无法完全解锁。如果线程在调用lock1时保持unlockFirst(),则在函数返回时它仍会保留lock1

如果您致电lock1.lock(),然后成功lock1.tryLock(),则需要致电lock1.unlock() 两次以完全解除锁定。你的代码没有这样做,因此陷入僵局。

答案 2 :(得分:-2)

您在所有线程中共享静态Locker。

在某个时刻线程将尝试tryLock(),而锁已被另一个线程持有。

编辑:不正确,忽略。