我注意到昨天的东西很奇怪。看来两个线程同时进入同一个对象锁定的两个同步块。同步部分不会阻止!
含有相关代码的类(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