多个线程持有同一把锁?

4
  "dashboardRefreshContainer-8" - Thread t@1384
   java.lang.Thread.State: RUNNABLE
    at sun.util.calendar.ZoneInfo.getLastRule(ZoneInfo.java:638)
    - locked <4d70153e> (a sun.util.calendar.ZoneInfo)
    at sun.util.calendar.ZoneInfo.getOffsets(ZoneInfo.java:275)
    at sun.util.calendar.ZoneInfo.getOffsets(ZoneInfo.java:225)
    at java.util.GregorianCalendar.computeFields(GregorianCalendar.java:2024)
    at java.util.GregorianCalendar.computeFields(GregorianCalendar.java:1996)
    at java.util.Calendar.setTimeInMillis(Calendar.java:1109)
    at java.util.Calendar.setTime(Calendar.java:1075)

"TP-Processor38" - Thread t@158
   java.lang.Thread.State: RUNNABLE
    at sun.util.calendar.ZoneInfo.getLastRule(ZoneInfo.java:638)
    - locked <4d70153e> (a sun.util.calendar.ZoneInfo)
    at sun.util.calendar.ZoneInfo.getOffsets(ZoneInfo.java:275)
    at sun.util.calendar.ZoneInfo.getOffsets(ZoneInfo.java:225)
    at java.util.GregorianCalendar.computeFields(GregorianCalendar.java:2024)
    at java.util.GregorianCalendar.computeFields(GregorianCalendar.java:1996)
    at java.util.Calendar.setTimeInMillis(Calendar.java:1109)
    at java.util.Calendar.setTime(Calendar.java:1075)

这两个线程都是可运行的,它们持有相同的锁。在它们都处于RUNNABLE状态时,这两个线程能够锁定相同的地址吗?这是JRE的一个bug吗?

4
我们在看什么?请为这个问题添加更多上下文。 - Paul Grime
亲爱的朋友,请同时添加相关代码。 - Mavrick
这是哪个JVM?(线程转储格式没有标准化,对吗?) - meriton
1个回答

11

问题仅存在于线程转储中。实际上,在任何时刻,锁只被一个线程持有。然而,线程转储显示了两个具有相同锁的不同线程,因为它不是原子的。

可以使用以下程序轻松地复现此行为:

public class Test {
    public static void main(String[] args) {
        Runnable runnable = new Runnable() {
            public void run() {
                for (;;) {
                    synchronized (this) { }
                }
            }
        };
        new Thread(runnable).start();
        new Thread(runnable).start();
    }
}

1
我使用这个作为一个测试案例来向Oracle报告一个错误:https://bugs.openjdk.java.net/browse/JDK-8036823 - rxg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接