繁体   English   中英

Java线程处理:在lock.wait()中提供超时参数时发生意外行为

[英]Java Threading: Unexpected behavior when providing timeout argument in lock.wait()

不幸的是,由于周围的代码过于复杂,因此我无法提供完整的上下文信息。 简短的是:

我有一段等待锁的代码:

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

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

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

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

同样,它应该非常简单(这可以在代码的其他几个地方按预期工作)。 但是,在这种情况下,执行基本上会暂停,直到发生超时为止。 关于发生的事情,我的唯一猜测是进入等待状态时不会释放锁-通知程序永远无法获取锁,因此等待会一直休眠直到超时。 更糟糕的是,这是一个阻塞性的睡眠-没有其他线程能够等待锁,这将强制执行完全同步。

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

任何想法将不胜感激。

作业系统: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()ing线程仍必须重新获取该锁:线程A等待条件变为真,线程B使条件变为真并调用notify(); 不能保证线程C不会首先获得该锁,并且在wait()调用能够返回之前再次使条件变为假。

同样,即使没有通知对象,也允许wait()返回(这称为“虚假唤醒”)。

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

除了在用于wait()和notify()调用的同一锁对象上同步时,什么都没有改变要等待的条件。

不管您是否提供超时,对象上的wait方法都将释放当前线程在对象上持有的锁(如John所评论)。

使用您提供的代码并基于对场景的描述,我想是在执行lock.wait(60000L)的那一刻,JVM释放了对象上的锁,同时可能拾取处于运行/运行状态的任何其他线程如果它们在同一个对象上进行同步,则它们可能在通知程序线程获得该锁定之前就获得了锁定。

此行为很难调试,因为它取决于JVM分析器来选择应运行的线程。 因此,正如您在执行lock.wait(60000L)时所解释的那样,不必总是使通知程序线程单独承担对公共对象的锁定。 如果还有其他线程也在公共对象上等待,那么它很可能最终获得锁定,从而导致通知程序线程无法获得锁定,因此lock.wait(60000L)超时。

每当使用lock.wait(..)时 ,都必须使用lock.notify()lock.notifyAll() 确保使用在逻辑上有意义的位置,并且它将在超时之前 “唤醒”锁(考虑您放置的超时值就足够了)。 这里是有关其用法的一些指南,我希望它有用: http : //www.javamex.com/tutorials/wait_notify_how_to.shtml

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM