有几个线程可以在同一个对象上等待吗?

时间:2015-10-13 09:38:30

标签: java multithreading

我有一个jstack转储,似乎说几个线程已经获得了对同一个对象的锁定。据我所知,这是不可能的,但是不是吗?

这里是try block中关键等待调用的代码:

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)的锁定并调用等等。我错了还是有几个线程真的获得了锁定并且在一个对象上调用了等待?

3 个答案:

答案 0 :(得分:5)

您的转储显示多个线程正在等待对象监视器(等待获取它),而不是多个线程(多个线程)已经获取它(同时)。前者很可能也很正常。后者不可能发生。

换句话说,是的,几个线程已经获得了锁定/监视器,但是这种情况是连续发生的(一个接一个)。一旦线程调用wait,它就会释放锁,然后另一个线程可以获取它(然后再次释放它,依此类推)。

答案 1 :(得分:5)

  

正如您所看到的,几个不同的线程(通过名称和tid线程ID)显然已在同一个UserInfo对象(0x000000008b8de758)上获得锁定,并在其上调用wait()。 / p>

这是绝对正确的。几个线程在同一个对象上调用了wait()。这听起来有点违反直觉,因为代码在synchronized块内。

documentation解释了这个“神秘”:wait() 的调用释放了监视器的所有权,让其他线程进入并开始等待,如果他们希望< / p>

  

当前线程必须拥有此对象的监视器。 线程释放此监视器的所有权并等待,直到另一个线程通过调用notify方法或notifyAll方法通知等待此对象监视器的线程唤醒。然后线程等待,直到它可以重新获得监视器的所有权并继续执行。 (强调添加)

答案 2 :(得分:0)

线程在Object的监视器上被阻塞,并且在任何时候都没有多个所有权。为了确保获取对象的公平性,您可以考虑使用Lock然后您可能知道任何特定线程是否需要时间完成并长期获得对象的监视器