Java 如何使多个线程具有“0”;“锁定”;在同一对象上(如线程转储中所示)

Java 如何使多个线程具有“0”;“锁定”;在同一对象上(如线程转储中所示),java,multithreading,jvm,thread-dump,Java,Multithreading,Jvm,Thread Dump,我有下面的线程转储,它显示了两个线程都锁定在同一个对象上。我不明白这到底意味着什么 "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) - w

我有下面的线程转储,它显示了两个线程都锁定在同一个对象上。我不明白这到底意味着什么

    "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)
“pool-1-thread-2”prio=10 tid=0x00007fd6dc106000 nid=0x5d15在对象中。等待()[0x00007fd6d2067000]
java.lang.Thread.State:正在等待(在对象监视器上)
在java.lang.Object.wait(本机方法)
-等待(一个java.lang.Object)
等待(Object.java:503)
test.TestDead$Foo.second(TestDead.java:22)
test.TestDead$Foo.first(TestDead.java:14)
-锁定(一个java.lang.Object)
test.TestDead$2.run(TestDead.java:45)
位于java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
在java.util.concurrent.FutureTask.run(FutureTask.java:262)处
位于java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
位于java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
运行(Thread.java:724)
锁定可拥有的同步器:
-(一个java.util.concurrent.ThreadPoolExecutor$Worker)
对象中的“pool-1-thread-1”优先级=10 tid=0x00007fd6dc104800 nid=0x5d14。等待()[0x00007fd6d2168000]
java.lang.Thread.State:正在等待(在对象监视器上)
在java.lang.Object.wait(本机方法)
-等待(一个java.lang.Object)
等待(Object.java:503)
test.TestDead$Foo.second(TestDead.java:22)
test.TestDead$Foo.first(TestDead.java:14)
-锁定(一个java.lang.Object)
test.TestDead$1.run(TestDead.java:37)
位于java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
在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)
运行(Thread.java:724)
锁定可拥有的同步器:
-(一个java.util.concurrent.ThreadPoolExecutor$Worker)
这里“锁定”的真正含义是什么?

在本文中,锁定意味着您正在运行的java代码已经进入了一个
同步块,但尚未退出该块

正如线程转储显示的那样,您正在调用
wait()
,这将在内部解锁与
synchronous
块关联的监视器。但是,由于您正在等待时阻塞,并且尚未退出同步块,因此线程转储仍然显示
已锁定
。因此,尽管底层监视器已解锁,但多个线程仍可能在线程转储中显示
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=0x00007f86c4080000 nid=0x5d35在Object.wait()中[0x00007f86cbae2000]
java.lang.Thread.State:正在等待(在对象监视器上)
在java.lang.Object.wait(本机方法)
-等待(测试监视器)
等待(Object.java:503)
在TestMonitor.lockAndWait(TestMonitor.java:5)
-锁定(测试监视器)
在TestMonitor.main(TestMonitor.java:13

注意:尽管处于等待状态,监视器仍处于锁定状态

更新 如果单线程的情况不能令人信服,您可以运行上面的示例(稍加修改),在这种情况下,您将在线程转储中的同一个监视器上看到多个线程
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();
}

谢谢你的链接。这正是我在转到StackOverflow之前阅读的页面。你能显示整个stacktraces吗?两个线程可以持有相同的锁,如果其中一个正在等待。@Banthar post更新。你能解释一下关于两个线程持有相同的锁的情况吗?我只是不明白。我想是“锁”应该由一个且只有一个线程持有。ThanksSince
wait()
是一个本机方法,我猜想
wait()
解锁监视器的事实不会在线程转储中得到报告。因此,两个线程都锁定监视器并调用
wait
(这会在内部解锁监视器)但它仍然在线程转储中显示为锁定。