我注意到昨天的東西很奇怪。看來兩個線程同時進入同一個對象鎖定的兩個同步塊。同步部分不會阻止!
含有相關代碼的類(MyClass
)類似於此:
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);
}
}
我創建運行上面的類我的應用程序的線程轉儲,並感到非常驚訝,因爲我看到了這一點:
"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)
...
(我改變了類和方法名稱爲簡單的情況下,所以不要被愚蠢的名字混淆。)
看來,THR EAD HTTP-8080-136和HTTP-8080-111雙雙獲得上myLock
鎖。它與對象地址是相同的對象:0x00007fd8a6b8c790
。 Java運行規範是怎麼了關鍵字:
synchronized語句獲得代表執行線程的互斥鎖(§17.1),執行塊,然後釋放鎖。雖然執行線程擁有鎖,沒有其他線程可以獲取鎖。 [The Java Language Specification, 14.19]
那麼這怎麼可能呢?
有在線程轉儲另一個44點一線「等待」的鎖。這是線程正在等待的樣子:
"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)
產生於退出信號發送到進程。我不知道Sun VM在線程轉儲期間的行爲如何。但我認爲這個過程已經停止了。否則,你會得到一個不一致的線程轉儲。 – 2010-07-13 09:19:54
我知道對於IBM JVM來說,這並不一定是真實的,但對SUN來說卻不太確定,但絕對要記住一些東西。 – 2010-07-13 09:25:29
本網站聲稱所有線程都處於暫停狀態:http://expertodev.wordpress.com/2009/05/30/how-to-take-java-thread-dump/ – 2010-07-13 09:44:34