Lock.tryLock():执行不同任务的线程?

时间:2018-02-15 18:24:13

标签: java multithreading locking java.util.concurrent fork-join

我试图理解Java中的多线程,使用  作为java.util.concurrent.*的一部分添加的功能。首先,有lock概念,线程可以尝试获取;如果线程无法获取,它可以执行其他一些任务。

我已经阅读了一些书中的在线资料,但从未见过他们在实际中实现的任何内容。如果一个线程无法获得锁定,它可以执行其他任务,这怎么可能呢?不是一个应该做单一工作的线程"?如果它能够/不能获得锁定,它如何具有多个逻辑执行?

是否有任何真正的实施,我可以参考,以了解,加强概念;否则它看起来太抽象了,如何在现实生活中实现。

有任何解释吗?

1 个答案:

答案 0 :(得分:3)

很难找到真实的例子,因为通常你不会设计你的软件来使用tryLock()。 javadoc中给出的示例如下:

Lock lock = ...;
if (lock.tryLock()) {
  try {
    // manipulate protected state
  } finally {
    lock.unlock();
  }
} else {
  // perform alternative actions
}

但你不会那样设计你的软件,不是吗?如果锁从未(或几乎从不)可用,会对您的程序产生怎样的影响?如果它始终可用怎么办?你有一种方法可以根据纯粹的机会做两件事之一。这不是好设计,它增加了随机性和复杂性。

好的,所以这不是你决定使用的东西,因为它很优雅。有什么好处?

想象一下,您继承了由insane programmer设计的遗留项目,并且存在严重的死锁问题。它周围有synchronized个方法,需要每周至少启动一次,因为它会锁定。首先,您将所有synchronized方法转换为使用Lock。现在你不再永远阻止synchronized,但可以使用tryLock(long, TimeUnit)来超时并防止死锁。

现在你已经解决了导致死锁的重启问题,但由于你花时间等待,它仍然不是最佳选择。通过额外的重构,您可以设法减少锁定,但遗憾的是,您还无法正确执行lock ordering。您的结束代码如下所示,其中使用tryLock()获取内部锁定或释放外部锁定以防止死锁:

Lock outerLock = ...;
outerLock.lock();  // Here we block freely
try {
   Lock innerLock = ...;
   if (innerLock.tryLock()) {  // Here we risk deadlock, we'd rather "fail-fast"
     try {
       doSomethingProtectedByLocks();
     } finally {
       innerLock.unlock();
     }
   } else {
     throw new OperationFailedException(); // Signal the calling code to retry
   }   
} finally {
   outerLock.unlock();
}

我认为问题主要在于措辞。 Javadoc讨论了基于锁是否被获取而执行的“动作”(如解锁外锁),但是很容易读取它,好像线程将由锁定状态确定2个单独的职责。