我正在修改一些非常复杂的代码,我需要在此之上添加我自己的同步。
但是,现有代码有大约十几个(如果不是更多的话)不同的锁,我的代码需要调用它的一些方法。我真的不知道获取锁的顺序,也无法真正控制它。
那么,我的问题是,如果我用一个锁替换所有不同的锁会发生什么?除了牺牲粒度外,还有其他我应该注意的问题吗?
谢谢!
最佳答案
如果您更改所有 synchronized
block (和方法)、和 所有其他阻塞结构,我认为您应该没问题 - 最坏的情况是您的应用退化为串行执行。但是如果你只改变其中的一些,你可能会陷入僵局。考虑两个线程各自获取多个锁的场景:
Thread 1:
synchronized A
synchronized B
Thread 2:
synchronized B
synchronized C
这里没有死锁的风险,但是如果用新的通用锁替换 A
和 C
(但不是 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/