【问题标题】:how can more than one thread have "locked" on the same object (as shown in a thread-dump)多个线程如何“锁定”同一个对象(如线程转储中所示)
【发布时间】:2015-05-07 21:19:38
【问题描述】:

我有以下线程转储,它显示两个线程都锁定在同一个对象上。我对它的真正含义感到困惑

    "pool-1-thread-2" prio=10 tid=0x00007fd6dc106000 nid=0x5d15 in Object.wait() [0x00007fd6d2067000]
   java.lang.Thread.State: WAITING (on object monitor)
    at java.lang.Object.wait(Native Method)
    - waiting on <0x00000007c3547770> (a java.lang.Object)
    at java.lang.Object.wait(Object.java:503)
    at test.TestDead$Foo.second(TestDead.java:22)
    at test.TestDead$Foo.first(TestDead.java:14)
    - locked <0x00000007c3547770> (a java.lang.Object)
    at test.TestDead$2.run(TestDead.java:45)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
    at java.util.concurrent.FutureTask.run(FutureTask.java:262)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:724)

   Locked ownable synchronizers:
    - <0x00000007c35519e8> (a java.util.concurrent.ThreadPoolExecutor$Worker)

"pool-1-thread-1" prio=10 tid=0x00007fd6dc104800 nid=0x5d14 in Object.wait() [0x00007fd6d2168000]
   java.lang.Thread.State: WAITING (on object monitor)
    at java.lang.Object.wait(Native Method)
    - waiting on <0x00000007c3547770> (a java.lang.Object)
    at java.lang.Object.wait(Object.java:503)
    at test.TestDead$Foo.second(TestDead.java:22)
    at test.TestDead$Foo.first(TestDead.java:14)
    - locked <0x00000007c3547770> (a java.lang.Object)
    at test.TestDead$1.run(TestDead.java:37)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
    at java.util.concurrent.FutureTask.run(FutureTask.java:262)
    atjava.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    atjava.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:724)

   Locked ownable synchronizers:
    - <0x00000007c3551730> (a java.util.concurrent.ThreadPoolExecutor$Worker)

“锁定”在这里的真正含义是什么?

【问题讨论】:

  • 感谢您的链接。这正是我在转向 StackOverflow 之前阅读的页面。
  • 你能显示整个堆栈跟踪吗?如果其中一个正在等待,两个线程可以持有相同的锁。
  • @Banthar 帖子已更新。你能解释一下两个线程持有同一个锁吗?我只是不明白。我认为“锁”应该由一个且只有一个线程持有。谢谢
  • 由于wait() 是本机方法,我的猜测是wait() 解锁监视器的事实不会在线程转储中报告。因此,两个线程都锁定了监视器并调用wait(它在内部将其解锁),但它仍然在线程转储中显示为锁定。

标签: java multithreading jvm thread-dump


【解决方案1】:

在此上下文中,locked 表示您正在运行的 java 代码已进入 synchronous 块,但尚未退出该块。

正如您的线程转储所示,您正在调用wait(),它在内部解锁了与synchronous 块关联的监视器。但是,由于您正在等待并没有退出同步块,因此线程转储仍然显示locked。因此,尽管底层监视器已解锁,但仍有可能在线程转储中显示多个线程 locked

这可以通过一个简单的测试很容易地证明:

public class TestMonitor {

    synchronized public void lockAndWait() {
        try {
            wait();
        } catch ( InterruptedException ex ) {
            // Stifle
        }
    }

    public static void main( String args[] ) {
        TestMonitor tm = new TestMonitor();
        tm.lockAndWait();
    }
}

运行时输出以下线程转储:

"main" prio=10 tid=0x00007f86c4008000 nid=0x5d35 in Object.wait() [0x00007f86cbae2000] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) - waiting on <0x0000000759055df8> (a TestMonitor) at java.lang.Object.wait(Object.java:503) at TestMonitor.lockAndWait(TestMonitor.java:5) - locked <0x0000000759055df8> (a TestMonitor) at TestMonitor.main(TestMonitor.java:13

请注意,尽管位于 wait 中,但监视器仍为 locked

更新

如果单线程情况不令人信服,您可以运行上面稍作修改的示例,在这种情况下,您将在线程转储的同一监视器上看到多个线程 locked

public static void main( String args[] ) {
    final TestMonitor tm = new TestMonitor();

    Thread thread1 = new Thread( new Runnable() { public void run() { tm.lockAndWait(); } } );
    Thread thread2 = new Thread( new Runnable() { public void run() { tm.lockAndWait(); } } );
    thread1.start();
    thread2.start();
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-03
    • 1970-01-01
    • 2023-03-21
    • 1970-01-01
    • 1970-01-01
    • 2023-03-19
    相关资源
    最近更新 更多