【问题标题】:why does the following code result in deadlock为什么下面的代码会导致死锁
【发布时间】:2011-11-16 11:24:44
【问题描述】:

我有以下课程

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

和储物柜类

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

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

【问题讨论】:

  • 如果你删除了第一个解锁,它仍然死锁吗?

标签: java multithreading locking


【解决方案1】:

lock1 被锁定两次:一次在 lockFirst 中,再次在 unlockFirst (lock1.tryLock()) 中,但在 unlockFirst 中仅解锁一次。

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

【讨论】:

  • 所以我必须解锁两次吗?
  • 只需删除 if(lock1.tryLock) 和第一次调用 unlockFirst。你需要吗?
  • 支持“被锁定两次”。 unlockFirst() 方法中的 tryLock() 绝对是问题所在。
  • @Tudor: 那么有没有办法通过当前线程解锁所有锁,或者需要多次调用解锁方法(Ps。我不需要lock.trylock,但是尝试一些场景)
  • 锁的第 1 和第 2 规则是:如果您有多个嵌套锁,则始终以锁定的相反顺序解锁,并且始终锁定和解锁相同的次数。所以嵌套 lock1 lock2 unlock2 unlock1 就是你所需要的。
【解决方案2】:

锁定了lock1,你永远不会完全解锁它。如果线程在调用unlockFirst()时持有lock1,那么当函数返回时,它仍然会持有lock1

如果您调用lock1.lock() 后成功调用lock1.tryLock(),则需要调用lock1.unlock() 两次 才能完全释放锁。您的代码没有这样做,因此出现了死锁。

【讨论】:

  • 这并不完全正确。他确实解锁了它,只是次数不够。
【解决方案3】:

您有一个在所有线程之间共享的静态 Locker。

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

编辑:不正确,忽略。

【讨论】:

  • 那又怎样? tryLock 旨在处理这个问题。
猜你喜欢
  • 1970-01-01
  • 2012-08-27
  • 2020-08-20
  • 2017-07-09
  • 2017-11-16
  • 2015-03-09
  • 2019-12-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多