I have the following thread-dump, which shows two threads both locking on the same object. And I'm confused as to what it really means
"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)
What does "locked" really mean here?
In this context, locked means that your running java code has entered a synchronous
block but not yet exited that block.
As your thread-dump shows, you are calling wait()
which internally unlocks the monitor associated with the synchronous
block. However, since you are blocking on wait and have not exited the synchronous block, the thread-dump still shows locked
. Thus it is possible to have multiple threads display locked
in the thread-dump despite the fact that the underlying monitor is unlocked.
This can be easily demonstrated with a simple test:
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();
}
}
which outputs the following thread-dump when run:
"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
Note the monitor is still locked
despite being in wait
.
In the event the single thread case isn't convincing, you can run the above example slightly modified in which case you'll see multiple threads locked
on the same monitor in the thread-dump:
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();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With