gpt4 book ai didi

java - 了解锁类与同步

转载 作者:行者123 更新时间:2023-11-30 08:38:17 25 4
gpt4 key购买 nike

在 Java Concurrency In Practice 中,我介绍了避免死锁的技术。他提出acquire在我们需要获取多个锁来保证一致性的时候使用tryLock()。如下:

public void m(MyObject o1, MyObject o2){
synchronized(o1){
synchornized(o2){
//...
}
}
}

我们最好使用这个:

public void m(MyObject o1, MyObject o2){
while(true){
if(o1.lock.tryLock(){
try{
if(o2.lock.tryLock(){
try{
//...
} finally {
o2.lock.unlock();
}
}
} finally {
o2.lock.unlock()
}
}
}
}

现在他去了:

This technique works only when the two locks are acquired together; if multiple locks are acquired due to nesting of method calls you cannot just realease the outer lock, even if you know you hold it.

不是很明显。为什么在方法中调用方法时不能使用this?能举个例子吗?

最佳答案

我刚刚查了一下书,发现引用的语句是在定时锁的上下文中进行的(使用tryLock(long time, TimeUnit unit)),但我认为它也适用对于您的 tryLock() 示例。

理论上,您仍然可以将此技术用于嵌套方法调用,但它很快就会变得笨拙。让我们考虑一个简单的例子,您尝试在方法 foo(Lock lock) 中获取一些锁,如果成功,几个堆栈帧之后您尝试在方法 中获取另一个锁bar(锁锁).

  • 如果您的两个方法都使用 while (true) 直到它们最终设法获得它们的锁,那么如果一个线程在foo(),另一个在foo()中获得了B,现在都在bar()中不停地旋转, 试图获取彼此的锁。
  • 如果只在foo()方法中循环,在获取锁不成功时从bar()返回,或许可以避免死锁,但是现在:
    • foo()bar() 紧耦合
    • 根据调用 bar() 的确切时间,获取第一个锁和获取第二个锁之间的漏洞窗口可能非常大
    • 您需要从 foo() 中的循环开始重新计算整个分支
    • 目标代码路径变得非常难以遵循且易于破解
  • 如果你使用定时锁,你仍然会遇到上面的一些问题,你需要处理InterruptedException,你需要决定你想如何循环。
    • 一般的技术已经很容易产生一些IllegalMonitorStateException,这不太好

如果您定期获取相同的锁子集并使用相同的资源子集,您可能需要考虑锁粗化(将几个锁合二为一)或重新定义资源保护策略,以便您无需在单个工作流中获取多个级别的锁。

附言经过几次尝试,我得到了 tryLock() 和定时 tryLock(long time, TimeUnit unit) 方法来处理上述两种方法,两种 -锁定方案。不太好,我可以很容易地看出 protected 部分中的简单更改会如何破坏整个方案或使其变得过于复杂。

关于java - 了解锁类与同步,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36675945/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com