示例场景:
- 创建两个同步集合(s1和s2)
- 将它们传递给两个线程(T1和T2)
- 启动线程
T1的run() : while (forever) s1.equals(s2)
T2的run() : while (forever) s2.equals(s1)
会发生什么? - 同步集合的equals方法会获取自身的锁
它计算传入参数的长度以及包含的内容,以确定是否相等[注意:这是我分析日志后的猜测]
如果传入的参数也是同步集合,则调用size()和containAll()需要获取该集合的锁。
在上面的示例中,T1和T2的锁获取顺序如下:
T1: s1 -> s2 T2: s2 -> s1
当然,这会导致死锁。
这个问题不仅仅与同步集合有关。即使使用哈希表或向量也可能发生这种情况。
我认为这是Java API的限制(设计)。如何克服这个问题?如何确保在我的应用程序中不会发生这种情况?是否有一些设计原则可以遵循,而不会陷入这种情况?
s2
锁的某个线程执行了您代码片段中的第一个操作,则可能会发生死锁。 - Stephen Cjava.util.concurrent.locks
,你可以对其进行编码来避免这种情况,但我会尝试编写一些更加明智的代码。 - Tom Hawtin - tackline