Tôi đã nhận thấy điều gì đó rất lạ hôm qua. Có vẻ như hai chủ đề đang nhập hai khối đồng bộ khóa trên cùng một đối tượng cùng một lúc.phần đồng bộ không chặn!
Lớp (MyClass
) chứa mã có liên quan trông tương tự như sau:
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);
}
}
Tôi tạo ra một bãi chứa thread của ứng dụng của tôi chạy lớp trên và đã rất ngạc nhiên khi tôi thấy điều này:
"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)
...
(Tôi đã thay đổi tên lớp và phương thức cho trường hợp đơn giản, do đó đừng nhầm lẫn với tên ngớ ngẩn.)
Có vẻ như là ead http-8080-136 và http-8080-111 đều có khóa trên myLock
. Nó là cùng một đối tượng như địa chỉ đối tượng là giống nhau: 0x00007fd8a6b8c790
. Java Runtime Đặc điểm kỹ thuật nói này về từ khóa synchronized
:
Một tuyên bố đồng bộ có được một khóa lẫn nhau-trừ (§17.1) thay mặt cho các chủ đề thực hiện, thực hiện một khối, sau đó ra mắt khóa. Trong khi chuỗi thực thi sở hữu khóa, không có chuỗi nào khác có thể lấy khóa. [The Java Language Specification, 14.19]
Vậy làm thế nào điều này thậm chí có thể?
Có 44 chủ đề khác trong chuỗi kết thúc "chờ" cho khóa. Đây là cách trông giống như một chuỗi đang chờ:
"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)
Bằng cách gửi tín hiệu QUIT để quá trình này. Tôi không biết làm thế nào Sun VM hoạt động trong quá trình đổ thread. Nhưng tôi cho rằng quá trình này bị tạm dừng. Nếu không, bạn sẽ nhận được một chuỗi không phù hợp. –
Tôi biết cho IBM JVM này không nhất thiết phải đúng, không chắc chắn về SUN, tuy nhiên, chắc chắn một cái gì đó để ghi nhớ. –
Trang web này tuyên bố rằng tất cả các chủ đề bị tạm dừng: http://expertodev.wordpress.com/2009/05/30/how-to-take-java-thread-dump/ –