2012-06-28 12 views
5

Các JVM nói với tôi rằng một bế tắc đã xảy ra:"Tìm thấy 1 bế tắc", nhưng dấu vết cho thấy không bị khóa bởi bất kỳ thread

Found one Java-level deadlock: 
============================= 
"TP-Processor107": 
    waiting for ownable synchronizer 0x00002aaaf58e70f0, (a java.util.concurrent.locks.ReentrantReadWriteLock$NonfairSync), 
    which is held by "indexTrackerThread3" 
"indexTrackerThread3": 
    waiting for ownable synchronizer 0x00002aaaf4394580, (a java.util.concurrent.locks.ReentrantReadWriteLock$NonfairSync), 
    which is held by "TP-Processor16" 
"TP-Processor16": 
    waiting for ownable synchronizer 0x00002aaaf58e70f0, (a java.util.concurrent.locks.ReentrantReadWriteLock$NonfairSync), 
    which is held by "indexTrackerThread3" 

Chúng ta có thể thấy rằng indexTrackerThread3 đang chờ đợi một nguồn lực được tổ chức bởi TP-Processor16, và ngược -versa. Đó thực sự là một bế tắc.

Chúng ta có thể thấy rằng indexTrackerThread3 đang chờ 0x00002aaaf4394580:

"indexTrackerThread3": 
    - parking to wait for <0x00002aaaf4394580> 

Câu hỏi của tôi:

Trong the threads dump, tại sao không có dòng - locked <0x00002aaaf4394580>?

Dường như 0x00002aaaf58e70f0 thực sự không bị khóa bởi bất kỳ chuỗi nào. Điều gì có thể khóa nó?

Trong tất cả tài liệu bế tắc tôi đã đọc (example), cho mỗi dòng - parking to wait for <0x123> khác nhau, luôn có một dòng - locked <0x123>. Vì vậy, tôi bắt đầu nghi ngờ một lỗi JVM. Tôi có hiểu nhầm điều gì đó không?

Lưu ý: Xin lỗi vì đã liên kết với pastebin, nhưng câu hỏi không phải là câu trả lời mà không có đổ đầy. Để ngắn gọn, tôi đã xóa tất cả các dòng có chứa "at", chúng không bao gồm bất kỳ thông tin khóa nào.

Trả lời

4

Gói java.util.concurrent sử dụng cơ chế đỗ xe bản địa, extralingual (cũng như các cơ chế gốc khác, chẳng hạn như so sánh và hoán đổi nguyên tử). Bạn có thể xem những gì tôi đang nói về here.

Mẫu bạn mô tả thường xảy ra trong kết xuất chuỗi bắt nguồn từ thành ngữ Java cổ điển synchronized(lock) { lock.wait(); }.

+0

Cảm ơn bạn đã liên kết! Bây giờ tôi đã làm quen với lớp Unsafe. Ngay cả khi thực hiện thông qua một cuộc gọi đến Unsafe.park, khóa vẫn đến từ một cuộc gọi Java, vậy tại sao phần 'locked <0x123> 'không được viết ở dòng đó? Tôi sẽ đánh giá cao bất kỳ tài liệu nào nói về vấn đề cụ thể của id không có mặt. –

0

Câu trả lời của Marko Topolnik là chính xác.

Đối với giải pháp cho vấn đề của bạn, JProfiler sẽ hiển thị cho bạn biểu đồ hoàn chỉnh về chuỗi và màn hình cho các tình huống khóa liên quan đến khóa từ gói java.util.concurrent.

Disclaimer: Công ty của tôi phát triển JProfiler

0

thứ khác nhau có thể bế tắc đề java, màn hình, hay còn gọi là từ khóa synchronized, chỉ có một điều.

A lock can be a built-in object monitor, an ownable synchronizer, or the Condition object associated with synchronizers.

Bạn cũng có thể khai thác trong các định nghĩa của ThreadMXBean.findDeadlockedThreads và ThreadMXBean.findMonitorDeadlockedThreads để biết thêm thông tin.

Theo như tôi quan tâm, đó là khóa màn hình và khóa java 5.

Trong kết xuất đề, kết hợp waiting to lock <0x123>locked <0x123> chỉ dành cho khóa màn hình. Với java 5 khóa bạn chỉ nhận được phần đầu tiên. Một cái gì đó như parking to wait for <0x456>. Sau đó, bạn tìm kiếm một số 0x456 trong kết xuất chuỗi, nhưng không tìm thấy ở đâu. Điều này là khó hiểu.

0

Độ phức tạp của phân tích Dump Thread cho loại bế tắc như vậy chủ yếu là do việc sử dụng gói java.util.concurrent. Điều này được xây dựng để tránh xa cách cổ điển và xâm nhập của việc đồng bộ hóa các đối tượng Java. Gói này rất hữu ích khi bạn muốn hạn chế các thao tác WRITE thành một mô hình Thread đơn lẻ trong khi cho phép các phép toán READ đồng thời. Cách tiếp cận này là rất tốt từ một phối cảnh điều chỉnh hiệu suất, tác dụng phụ là mức độ phức tạp tăng lên của quá trình phân tích Dump Thread khi xử lý các vấn đề đồng thời.

Tôi khuyên bạn cũng nên xem lại bài viết sau. Nó mô tả các vấn đề như hidden Java deadlock kịch bản mà JVM thậm chí sẽ không thể phát hiện bế tắc (do khóa READ thường không được thiết kế để có khái niệm về quyền sở hữu). Chương trình Java mẫu được cung cấp làm ví dụ.

0

Theo dõi ngăn xếp cho biết 0x00002aaaf4394580 không bị khóa bởi bất kỳ chuỗi nào. Điều này có thể xảy ra do Java bug #6822370. Quan sát này nên thêm đóng cửa vào voted answer.