【问题标题】:notify() before exiting the synch'd block?在退出同步块之前通知()?
【发布时间】:2014-08-04 17:52:31
【问题描述】:

notify() 中是否有任何使用作为同步块中的最后一条语句?

例如:假设以下代码在某个线程r中运行,

    synchronized(t) {
        t.start();
        // do stuff using t
        t.notify();
    }

如果我删除线我会松动什么?

    t.notify();

线程r 已经在释放t 的锁,这个锁可供等待它的人使用。

我处理的代码示例在有和没有t.notify() 调用的情况下“表现”相同。

我能想到的唯一用途是,有点“主动”地通知t 的监视器正在被释放,等待它的人将进入BLOCKED 状态,等待获取它。 但是,在这种情况下notify() 是同步块中的最后一条语句,JVM 通过退出同步块已经知道该锁已释放。

这是一个关于了解notify()notifyAll() 的一些细节的问题。

TIA。

请注意:我见过Java notify() run before wait()?Does the position of the notify() call matter?(Java)。这是与那些不同的Q。

//=================================

编辑:示例代码:

    public class T3 {

        public static void main(String[] args){
            Sum t = new Sum();
            synchronized(t) {
                t.start();
                try { 
                    t.wait(); 
                } catch (InterruptedException ex) { 
                }
            }        
            System.out.println("Sums up to: " + t.sum);
        }    // main
    }

    class Sum extends Thread {
        int sum;

        public void run() {
            synchronized(this) {
                for(int i = 1; i <= 55 ; sum += i++);
    //          notify();
            }
        }
    }

Sum类的run()如下:

        public void synchronized run() {
            for(int i = 1; i <= 55; sum += i++);
    //      notify();
        }

【问题讨论】:

  • 我认为您在同步和等待/通知之间感到困惑。它们是相关的,但非常不同。请注意,您不应在 Thread 引用上使用同步或等待/通知,因为实现本身就是这样做的。
  • 我的理解是,如果其他人是 wait()ed,您只需要 notify(),但是仅在同步块的上下文中,您不需要它除非在你的程序的其他地方你 wait() 东西
  • @Aaron 在有和没有 notify() 的情况下工作相同,即使该对象上有线程 wait() 。
  • @JonSkeet “实验代码以放置我放置的概念”。试试这个。
  • @user3880721 "即使在该对象上有线程 wait() 时,也可以在有和没有 notify() 的情况下工作。" 你介意发布完整的示例,让我们重现是吗?

标签: java multithreading


【解决方案1】:

如果你锁定了一个线程,并且线程终止了,它会发送一个 notifyAll 给任何等待它的线程。见API documentation for Thread.join

此实现使用以 this.isAlive 为条件的 this.wait 调用循环。当线程终止时,将调用 this.notifyAll 方法。建议应用程序不要在 Thread 实例上使用 wait、notify 或 notifyAll。

在您的示例中,通知是线程完成执行之前完成的最后一件事,因此显式通知是多余的。

(请注意,此处引用的 API 文档和 Jon Skeet 都建议您不要锁定线程对象。)

【讨论】:

  • 谢谢 - 这解释了。您知道使线程脱离 WAITING 状态的具体情况是什么吗?到目前为止,它是 notify()/notifyAll() 并且锁本身进入了 TERMINATED 状态。
  • @user3880721:如果线程被中断,或者如果您在超时时调用等待,或者无缘无故(“虚假唤醒”),线程将退出等待状态。但是中断是为了取消线程,并且虚假唤醒很少见。如果没有通知,请使用超时。
  • 中断使线程脱离其wait()(或睡眠()或加入())-我不明白它是如何相关的(?)它取决于线程本身如何捕获InterruptedException。如果线程是这样捕获的,它会与线程变为 TERMINATED 相同。
  • @user3880721 它只是相关的,因为您要求的东西会使线程停止等待。它用于向线程发出信号,它是时候完成了,我不会用它来唤醒等待中的线程。
【解决方案2】:

是的。它允许在t 上运行wait() 的其他线程再次运行,而不是等待永远不会出现的通知。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-24
  • 2010-10-09
  • 1970-01-01
  • 1970-01-01
  • 2023-03-27
相关资源
最近更新 更多