2015-10-13 18 views
5

Tôi có một bãi chứa jstack dường như nói rằng một số chủ đề đã có được một khóa trên cùng một đối tượng. Khi tôi hiểu điều này được cho là không thể nhưng phải không?Có thể cho một số chủ đề chờ đợi trên cùng một đối tượng không?

Dưới đây là đoạn code với các cuộc gọi chờ đợi quan trọng bên trong khối try:

protected boolean waitMaxWaitingTime(UserInfo aUserInfo) throws EventServiceException { 
    final int theMaxWaitingTime = myConfiguration.getMaxWaitingTime(); 
    if(theMaxWaitingTime <= 0) { 
     return true; 
    } 
    if(aUserInfo.isEventsEmpty()) { 
     //monitor for event notification and double checked 
     synchronized(aUserInfo) { 
      if(aUserInfo.isEventsEmpty()) { 
       try { 
        final long theStartTime = System.currentTimeMillis(); 
        // --- THE CRUCIAL WAIT CALL --- 
        aUserInfo.wait(theMaxWaitingTime); 
        return (System.currentTimeMillis() - theStartTime >= theMaxWaitingTime); 
       } catch(InterruptedException e) { 
        throw new EventServiceException("Error on waiting max. waiting time!", e); 
       } 
      } 
     } 
    } 
    return false; 
} 

Và đây là jstack bãi (có chọn lọc):

"thread-79" #161 daemon prio=5 os_prio=0 tid=0x000000005d63c000 nid=0x322c in Object.wait() [0x000000007e93c000] 
    java.lang.Thread.State: TIMED_WAITING (on object monitor) 
    at java.lang.Object.wait(Native Method) 
    at de.novanic.eventservice.service.connection.strategy.connector.ConnectionStrategyServerConnectorAdapter.waitMaxWaitingTime(ConnectionStrategyServerConnectorAdapter.java:92) 
    - locked <0x000000008b8de758> (a de.novanic.eventservice.service.registry.user.UserInfo) 

"thread-77" #159 daemon prio=5 os_prio=0 tid=0x000000005d63a800 nid=0x5384 in Object.wait() [0x000000007e83c000] 
    java.lang.Thread.State: TIMED_WAITING (on object monitor) 
    at java.lang.Object.wait(Native Method) 
    at de.novanic.eventservice.service.connection.strategy.connector.ConnectionStrategyServerConnectorAdapter.waitMaxWaitingTime(ConnectionStrategyServerConnectorAdapter.java:92) 
    - locked <0x000000008b8de758> (a de.novanic.eventservice.service.registry.user.UserInfo) 

"thread-74" #156 daemon prio=5 os_prio=0 tid=0x000000006efe6000 nid=0x4828 in Object.wait() [0x000000007e25c000] 
    java.lang.Thread.State: TIMED_WAITING (on object monitor) 
    at java.lang.Object.wait(Native Method) 
    at de.novanic.eventservice.service.connection.strategy.connector.ConnectionStrategyServerConnectorAdapter.waitMaxWaitingTime(ConnectionStrategyServerConnectorAdapter.java:92) 
    - locked <0x000000008b8de758> (a de.novanic.eventservice.service.registry.user.UserInfo) 

Như bạn có thể thấy, chủ đề khác nhau (đi bằng tên và ID chủ đề tid, trong chủ đề này thread-79thread-74) dường như đã mua một khóa trên cùng một đối tượng UserInfo (0x000000008b8de758) và được gọi là chờ trên đó. Tôi có nhầm lẫn hoặc có một số chủ đề thực sự có được khóa và được gọi là chờ đợi trên một đối tượng duy nhất?

+2

'if' phải là' while'. – EJP

+0

Ngoại trừ nếu 'aUserInfo.isEventsEmpty()' có ["xảy ra trước"] (https://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.4.5) ràng buộc. Bạn không được sử dụng DCL. JVM được tự do sắp xếp lại các hướng dẫn miễn là các ràng buộc "xảy ra trước" được lấp đầy. Nói cách khác, tình trạng của bạn có thể đúng nếu không có tất cả các hoạt động giả định được xử lý. Ví dụ: bạn đặt giá trị boolean thành true sau khi đặt thuộc tính.JVM có thể thiết lập boolean trước khi thiết lập thuộc tính và thậm chí có thể phân bổ thuộc tính, thiết lập boolean thành true và cuối cùng là quá trình khởi tạo cá thể (gọi hàm dựng). – LoganMzz

+0

@EJP Và 'return' phải được thực hiện sau vòng lặp;) – LoganMzz

Trả lời

5

Kết xuất của bạn cho thấy một số chuỗi đang chờ trên màn hình đối tượng (chờ lấy), và không phải là một số chuỗi (nhiều hơn một) đã mua nó (cùng một lúc). Trước đây là khá tốt và bình thường. Cái sau không thể xảy ra.

Nói cách khác, có, một số chủ đề đã có được khóa/giám sát nhưng điều đó đã xảy ra serially (cái này sau cái kia). Khi một cuộc gọi chờ đợi, nó sẽ giải phóng khóa và sau đó một luồng khác có thể có được nó (và sau đó giải phóng nó một lần nữa, vv).

+0

Hơn nữa, không cần nhả khóa màn hình khi chờ, sẽ không thể 'thông báo' được! – LoganMzz

0

Chủ đề bị chặn trên màn hình của đối tượng và không có nhiều quyền sở hữu tại bất kỳ thời điểm nào. Để đảm bảo tính công bằng cho việc mua đối tượng, bạn có thể xem xét sử dụng Lock và sau đó bạn có thể biết có bất kỳ chủ đề cụ thể nào không. đã mua màn hình của một đối tượng trong một thời gian dài của thời gian

5

Như bạn có thể thấy, chủ đề khác nhau (đi bằng tên và ID chủ đề tid) có vẻ mua một ổ khóa trên cùng một UserInfo đối tượng (0x000000008b8de758) và gọi wait() vào nó .

Điều này hoàn toàn đúng. Một số chủ đề được gọi là wait() trên cùng một đối tượng. Điều này nghe có vẻ phản trực giác lúc đầu, bởi vì mã nằm trong một khối synchronized.

Các documentation giải thích điều này "bí ẩn": tiếng gọi của wait()phát hành quyền sở hữu màn hình, cho phép chủ đề khác nhập và bắt đầu chờ đợi nếu họ muốn

Các thread hiện hành phải sở hữu này của đối tượng màn hình. Chủ đề giải phóng quyền sở hữu của màn hình này và chờ cho đến khi một luồng khác thông báo các chuỗi đang chờ trên màn hình của đối tượng này để đánh thức hoặc thông qua một cuộc gọi đến phương thức thông báo hoặc phương thức notifyAll. Sau đó, chuỗi chờ cho đến khi nó có thể lấy lại quyền sở hữu màn hình và tiếp tục thực hiện. (được thêm vào)

Các vấn đề liên quan