java - 线程锁排序与简单的同步块(synchronized block)

标签 java multithreading locking

在阅读 Java Concurrency in Practice 这本书时,遇到了这段代码,其中“fromAccount”和“toAccount”对象被一个接一个地锁定,以防止动态锁定顺序死锁。

public void transferMoney(Account fromAccount,Account toAccount) {
    **synchronized (fromAccount) {**
        **synchronized (toAccount) {**
               ........
        }
    }
}

我很困惑为什么需要这个锁顺序。如果我们只是想确保两个对象同时被锁定,那么如果只是定期同步,你不会得到相同的效果吗在其中访问 fromAccount 和 toAccount 对象的 block 。我确信我在这里遗漏了一些基本概念。感谢您的帮助。

public void transferMoney(Account fromAccount,Account toAccount) {
    synchronized (this) {
        fromAccount.someMethod();
        toAccount.someMethod();        
    }
}

最佳答案

您要避免使用锁排序示例的替代方法:拥有一个一切都在使用的中央锁,因为这样您就不会获得并发传输,一切都在等待那个锁,并且只有一个传输可以在一个时间。目前还不清楚 this 是什么或者它的范围可能是什么,但是如果这个转账服务有多个实例,那么锁定就没有任何好处,因为涉及一个账户的一次转账可以通过一个账户例如,涉及同一账户的另一笔转账可以通过另一个账户进行。因此,似乎只能有其中之一,这会将您的并发性减少到一次传输。您不会死锁,但也不会快速处理大量传输。

这个玩具示例(你不应该把它误认为任何人如何转账)背后的想法是它试图通过锁定参与转账的个人账户来获得更好的并发性,因为对于很多转账涉及的帐户不涉及其他并发传输,您希望能够并发处理它们并通过最小化对单个帐户的锁定范围来最大化您的并发性。但是,如果某个帐户涉及多个并发传输并且某些传输以不同的顺序获取锁,则此方案会遇到麻烦。

关于java - 线程锁排序与简单的同步块(synchronized block),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32146512/

相关文章:

Java有效实现Thread

c++ - 在 C++ 中获取一个只有一次有效的锁

windows - 有没有办法用 Java 锁定目录?

c# - await Task<T> 和 Task<T>.Result 有什么区别?

java - 使用 Java 消息服务 (JMS) 进行点对点通信

Java Swing 未正确显示

java - 用ant执行java类

swift 并发: Why Task is not executed on other background thread

xcode - 如果 index.lock 存在,有没有办法让 git 自动重试命令?

Java DateFormat 返回错误的日期