java - 修复困惑代码中的死锁

标签 java multithreading synchronization locking

我正在修改一些非常复杂的代码,我需要在此之上添加我自己的同步。

但是,现有代码有大约十几个(如果不是更多的话)不同的锁,我的​​代码需要调用它的一些方法。我真的不知道获取锁的顺序,也无法真正控制它。

那么,我的问题是,如果我用一个锁替换所有不同的锁会发生什么?除了牺牲粒度外,还有其他我应该注意的问题吗?

谢谢!

最佳答案

如果您更改所有 synchronized block (和方法)、 所有其他阻塞结构,我认为您应该没问题 - 最坏的情况是您的应用退化为串行执行。但是如果你只改变其中的一些,你可能会陷入僵局。考虑两个线程各自获取多个锁的场景:

Thread 1:
    synchronized A
        synchronized B

Thread 2:
    synchronized B
        synchronized C

这里没有死锁的风险,但是如果用新的通用锁替换 AC(但不是 B),那么你将拥有:

Thread 1:
    synchronized L
        synchronized B

Thread 2:
    synchronized B
        synchronized L

...这是典型的死锁情况。

考虑另一种情况,锁本身不提供死锁,而是死锁一个像 CountDownLatch 这样的阻塞类:

Thread 1:
    synchronized A
        latch L.countDown()

Thread 2:
    synchronized B
        latch L.await()

在这种情况下,将两个 synchronized block 更改为锁定公共(public)锁不会导致它们之间发生死锁,但如果线程 2 首先获得锁,则会导致死锁:它将等待闩锁的countDown,它永远不会到来,因为线程 1 在其 synchronized 入口点被阻塞。这个例子也适用于其他阻塞结构:信号量、阻塞队列等。

关于java - 修复困惑代码中的死锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10043432/

相关文章:

java - Spring xml ...有条件加载变量

c++ - 分割数据进行多线程处理

java - 同步语句之外的代码语句是线程安全的吗?

java - servlet的使用比struts2中的action-classes好吗?

c++ - 克隆/fork、信号量等进程同步算法编程时从哪里开始

java - 并发问题: Synchronized methods

c++ - 在不阻塞的情况下唤醒多个等待线程的最便宜方法

java - Hibernate 找不到现有字符串

java - 使用 Lambda 代理集成通过 API Gateway 从 AWS Lambda 抛出错误

java - 从 Java 调用 SSL URL 会出现证书问题