2015-10-13 36 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方法的调用,通知等待此对象监视器的线程唤醒。该线程然后等待,直到它可以重新获得监视器的所有权并恢复执行。 (强调增加)

相关问题