我试图理解Java中的多线程,使用
作为java.util.concurrent.*
的一部分添加的功能。首先,有lock
概念,线程可以尝试获取;如果线程无法获取,它可以执行其他一些任务。
我已经阅读了一些书中的在线资料,但从未见过他们在实际中实现的任何内容。如果一个线程无法获得锁定,它可以执行其他任务,这怎么可能呢?不是一个应该做单一工作的线程"?如果它能够/不能获得锁定,它如何具有多个逻辑执行?
是否有任何真正的实施,我可以参考,以了解,加强概念;否则它看起来太抽象了,如何在现实生活中实现。
有任何解释吗?
答案 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个单独的职责。