Java 线程 : Unexpected behavior when providing timeout argument in lock. wait()

标签 java multithreading mutex

不幸的是,我无法提供完整的上下文,因为周围的代码太复杂了。其缺点是:

我有一段代码正在等待锁:

            synchronized (lock) {
                lock.wait();
            }

按预期工作。相当简单——它获取锁,在开始等待时释放锁,另一个线程获取锁,然后通知它。

但是,一旦我提供超时,行为就会完全改变。

            synchronized (lock) {
                lock.wait(60000L);
            }

同样,应该相当简单(并且这在代码中的其他几个地方按预期工作)。然而,在这种情况下,执行基本上会停止,直到发生超时。我对似乎发生的事情的唯一猜测是,当它进入等待时,它不会释放锁——通知程序永远无法获取锁,因此等待会 hibernate 直到超时。更糟糕的是,这是一个阻塞 sleep - 没有其他线程能够等待该锁,并且它强制执行完全同步。

有人对这里可能发生的事情有任何想法吗?这是一个相当简单的函数,并且嵌套同步块(synchronized block)在任何时候都不会发生任何奇怪的事情。考虑到不提供超时,它应该无限期地等待,如果通知程序本身被破坏,代码将永远挂起,但事实并非如此。一旦提供超时,它就会停止工作。

任何想法将不胜感激。

操作系统:OS X 10.8.5

JDK:1.6.0、1.7.0.45 和 1.7.0.67

最佳答案

您的示例未显示 wait() 调用周围的 while() 循环。这表明您可能不完全理解等待和通知的用例。这是一个例子:

// This object is used to synchronize *EVERY* method
// that can change the value of count.
final Object lock = new Object();

int count;

void waiter() {
    synchronized(lock) {
        while(count <= 0) {
            lock.wait();
        }
        //do something that you are only allowed to do
        //when count > 0.
    }
}

void notifier() {
    synchronized(lock) {
        count++;
        if (count >= 0) {
            lock.notify();
        }
    }
}

[编辑:添加了这一段,感谢 Nathan Hughes 提醒我...] wait() 调用处于循环中,因为 wait() 线程在锁被释放后仍然必须重新获取锁。 notified:如果线程A正在等待条件成立,而线程B使条件成立并调用notify();无法保证线程 C 不会首先获得锁,并在 wait() 调用返回之前再次使条件为 false。

此外,即使没有通知对象(这称为“虚假唤醒”),wait() 也可以返回。

要等待的条件在代码中是明确的(即 count > 0)。

除非在用于 wait() 和 notification() 调用的同一个锁对象上进行同步,否则不会改变等待条件。

关于Java 线程 : Unexpected behavior when providing timeout argument in lock. wait(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25209599/

相关文章:

c - pthread_kill 与 pthread_cond_signal 在特定点暂停/恢复线程

c - 在信号处理程序中销毁 pthread mutex/rwlock

java - java中如何仅在动画完成后调用方法?

java - 我可以使用 jpa/hibernate 一次性执行批量查询吗?

multithreading - 如何向 iced 应用程序发送消息

multithreading - Haskell - 关于 System.Process 和多线程的一些问题

Posix 线程的条件变量

java - getResource 无法导出到 jar 中

java - Apache HttpClient 4.1 - 代理身份验证

c++ - DLL 互斥 - 一个例子