2015-10-13 35 views
5

我有一個jstack轉儲,看似說,有幾個線程獲得了同一個對象的鎖。據我所知,這是不可能的,但是嗎?幾個線程可能在同一個對象上等待嗎?

下面是用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; 
} 

而這裏的jstack轉儲(選擇):

"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) 

正如你所看到的,有幾個不同的線程(會通過名稱和tid線程ID,在此線程中thread-79thread-74)明顯獲得了對同一個UserInfo對象(0x000000008b8de758)的鎖定並對其調用wait。我是否錯誤或有幾個線程真的獲得了鎖,並稱之爲等待一個對象?

+2

'if'應該是'while'。 – EJP

+0

除非'aUserInfo.isEventsEmpty()'具有[ 「之前發生」](https://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.4.5 )約束。你不能使用DCL。只要「發生之前」約束被填充,JVM就可以自由地重新排序指令。換句話說,在沒有處理所有假定的操作的情況下,您的情況可能是真的。例如:設置一個屬性後,您將布爾值設置爲true。JVM可以在設置屬性之前設置布爾值,甚至可以分配屬性,將布爾值設置爲true,最後處理實例初始化(構造函數調用)。 – LoganMzz

+0

@EJP並且'return'必須在循環之後完成;) – LoganMzz

回答

5

轉儲顯示多個線程正在等待的對象監視器(等待獲取它),而不是多個線程(不止一個)已經獲得它(在同一時間)。前者很可能,也很正常。後者不可能發生。

換句話說,是的,多個線程已獲得鎖定/顯示器,但所發生串聯(一前一後)。一旦線程調用等待,它釋放鎖,然後另一個線程可以獲得它(然後再次釋放,等等)。

+0

此外,如果不在'wait'上釋放監視器鎖,就不可能'通知'! – LoganMzz

0

的線程被阻塞對象的監視器上,並沒有多種所有制在time.To的任何一點保證公平獲取的對象,可以考慮使用Lock然後如果任何特定線程需要時間來完成,你可以知道,且收購對象的監視器的時間

5

長時間正如你所看到的,有幾個不同的線程(通過名稱和TID線程ID會)顯然已經取得相同UserInfo對象(0x000000008b8de758)的鎖,而它叫wait()

這是絕對正確的。多個線程在同一個對象上調用wait()。這聽起來有點違反直覺,因爲代碼位於​​區塊內。

documentation解釋了這個「謎」:的wait()釋放監視的所有權的通話,讓其他線程進入,如果他們希望

當前線程必須擁有啓動等待此對象的監控。 線程釋放此監視器的所有權,並等待另一個線程通知對通知方法或notifyAll方法的調用,通知等待此對象監視器的線程喚醒。該線程然後等待,直到它可以重新獲得監視器的所有權並恢復執行。 (強調增加)

相關問題