Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how can more than one thread have "locked" on the same object (as shown in a thread-dump)

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?

like image 807
One Two Three Avatar asked May 07 '15 21:05

One Two Three


1 Answers

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.

UPDATE

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();
}
like image 149
Andy Avatar answered Oct 29 '22 16:10

Andy