The synchronized partition is not locked!

Yesterday I noticed something very strange. It seems that two threads simultaneously enter two synchronized blocks on the same object.

The class ( MyClass ) containing the corresponding code looks something like this:

 private static int[] myLock = new int[0]; protected static int methodA(final long handle, final byte[] sort) { synchronized (myLock) { return xsMethodA(handle, sort); } } protected static int methodB(final long handle) { synchronized (myLock) { return xsMethodB(handle); } } 

I dumped the stream of my application working on the class, and was very surprised to see this:

 "http-8080-136" daemon prio=10 tid=0x00000000447df000 nid=0x70ed waiting for monitor entry [0x00007fd862aea000] java.lang.Thread.State: BLOCKED (on object monitor) at com.MyClass.methodA(MyClass.java:750) - locked <0x00007fd8a6b8c790> (a [I) at com.SomeOtherClass.otherMethod(SomeOtherClass.java:226) ... "http-8080-111" daemon prio=10 tid=0x00007fd87d1a0000 nid=0x70c8 waiting for monitor entry [0x00007fd86e15f000] java.lang.Thread.State: BLOCKED (on object monitor) at com.MyClass.methodB(MyClass.java:991) - locked <0x00007fd8a6b8c790> (a [I) at com.SomeOtherClass.yetAnotherMethod(SomeOtherClass.java:3231) ... 

(I changed the names of the classes and methods for simplicity, so do not confuse the stupid names.)

It seems that the streams http-8080-136 and http-8080-111 both acquired a lock on myLock . This is the same object as the object address: 0x00007fd8a6b8c790 . The Java Runtime specification speaks of the synchronized :

The synchronized statement obtains a mutual exclusion lock (§17.1) on behalf of the executing thread, executes the block, and then releases the lock. As long as the executing thread holds the lock, no other thread can get the lock . [ Java Language Specification, 14.19 ]

How is this possible?

There are another 44 threads in the thread date for blocking. It looks like this if the thread is expecting:

 "http-8080-146" daemon prio=10 tid=0x00007fd786dab000 nid=0x184b waiting for monitor entry [0x00007fd8393b6000] java.lang.Thread.State: BLOCKED (on object monitor) at com.MyClass.methodC(MyClass.java:750) - waiting to lock <0x00007fd8a6b8c790> (a [I) at com.SomeOtherClass.yetAnoterMethod2(SomeOtherClass.java:226) 
+7
java multithreading concurrency synchronized
source share
4 answers

I asked the same question on the hotspot-dev mailing list and got a very good answer from Christopher Phillips:


Hello edward

I think this is a thread dump that is misleading.

If you really think that 2 are in the castle at the same time, you should probably get gcore (which is externally consistent).

The state you see is “waiting for the monitor to enter” is actually MONITOR_WAIT, which can represent the following code before actually acquiring the hot lock: (also see OSThreadContendState in osThread.hpp), called from: CSI / share / VM / run /synchronizer.cpp

 3413 OSThreadContendState osts(Self->osthread()); 3414 ThreadBlockInVM tbivm(jt); 3415 3416 Self->set_current_pending_monitor(this); 3417 3418 // TODO-FIXME: change the following for(;;) loop to straight-line code. 3419 for (;;) { 3420 jt->set_suspend_equivalent(); 3421 // cleared by handle_special_suspend_equivalent_condition() 3422 // or java_suspend_self() 3423 3424 EnterI (THREAD) ; 3425 3426 if (!ExitSuspendEquivalent(jt)) break ; 3427 3428 // 3429 // We have acquired the contended monitor, but while we were 3430 // waiting another thread suspended us. We don't want to enter 3431 // the monitor while suspended because that would surprise the 3432 // thread that suspended us. 

Chris

+4
source share

How was the stream shot made? If the threads were not suspended, the ownership of the lock could be changed between resetting one thread and the next.

+1
source share

I think the relevant information is “Waiting for monitor recording”, which is the same for both threads. Since both streams (in the stream dump) are marked with daemon streams, I assume that there should be a main stream at the same time. Is it possible that the main thread is the current owner of the monitor, which is blocking the other two threads?

0
source share

They did not acquire a lock, otherwise you will see xsMethodA or xsMethodB on the stack.

0
source share

All Articles