看到各种锁相关的问题和(几乎)总是发现'循环,因为虚假的唤醒'术语1我想知道,有没有人经历过这样的唤醒(假设一个体面的硬件/软件环境为例)?

我知道“虚假”这个词的意思是没有明显的原因,但这种事件的原因是什么呢?

(1注意:我不是在质疑循环实践。)

编辑:一个辅助问题(对于那些喜欢代码示例的人):

如果我有下面的程序,我运行它:

public class Spurious {
    public static void main(String[] args) {
        Lock lock = new ReentrantLock();
        Condition cond = lock.newCondition();
        lock.lock();
        try {
            try {
                cond.await();
                System.out.println("Spurious wakeup!");
            } catch (InterruptedException ex) {
                System.out.println("Just a regular interrupt.");
            }
        } finally {
            lock.unlock();
        }
    }
}

我能做些什么来唤醒这个等待,而不是永远等待一个随机事件?


当前回答

卡梅伦·珀迪(Cameron Purdy)不久前写了一篇博文,讲述了自己被假醒问题困扰的经历。所以,是的,它发生了

我猜这是在规范中(作为一种可能性),因为Java部署在一些平台上的限制?虽然我可能错了!

其他回答

卡梅伦·珀迪(Cameron Purdy)不久前写了一篇博文,讲述了自己被假醒问题困扰的经历。所以,是的,它发生了

我猜这是在规范中(作为一种可能性),因为Java部署在一些平台上的限制?虽然我可能错了!

https://stackoverflow.com/a/1461956/14731很好地解释了为什么需要防范虚假唤醒,即使底层操作系统没有触发它们。有趣的是,这种解释适用于多种编程语言,包括Java。

维基百科上关于假醒的文章有这样的花边新闻:

Linux中的pthread_cond_wait()函数是使用futex系统调用实现的。Linux上的每个阻塞系统调用在进程接收到信号. ...时突然返回EINTRPthread_cond_wait()不能重新启动等待,因为它可能会在futex系统调用之外的一小段时间内错过真正的唤醒。这种竞争条件只能通过调用方检查不变量来避免。因此,POSIX信号将产生伪唤醒。

概要:如果一个Linux进程收到信号,它的等待线程将享受一个漂亮的、热的伪唤醒。

我相信。这比通常给出的含糊的“为了性能”的理由更容易接受。

我有一个展示这种行为的生产系统。 线程等待队列中有消息的信号。 在繁忙期间,高达20%的唤醒是假的(即当它醒来时队列中没有任何东西)。 这个线程是消息的唯一消费者。 它运行在Linux SLES-10 8处理器盒上,使用GCC 4.1.2构建。 这些消息来自外部源,并且是异步处理的,因为如果我的系统读取它们的速度不够快,就会出现问题。

再加上这个。是的,这种情况会发生,我花了三天时间在24核机器(JDK 6)上寻找多线程问题的原因。10次执行中有4次遇到这种情况,没有任何模式。这从未发生在2核或8核上。

我研究了一些网上的资料,这不是Java的问题,而是一种普遍罕见但意料之中的行为。