代码与notify和notifyAll /同步(帮助理解)

时间:2016-11-21 21:54:39

标签: java multithreading notify

我正在从我的教授的书中学习考试,这段代码使用线程和同步:我们希望每次状态发生变化时都会收到通知(不会错过状态更改)。

public class C {

    private int state = 0; // the state
    private boolean modified = false; // to show if the state was changed since actualization

    public synchronized void printNewState() {
        while (true) {
            if (!modified) {
                wait();
            }
            System.out.println(state);
            modified = false;
            notify();
        }
    }

    public synchronized void setValue(int v) {
        if (modified) {
            wait();
        }
        state = v;
        notify();
        modified = true;
        System.out.println("value set");
    }
}

然后它写了:
但是,无法保证方法SetValue(int)中的notify()唤醒printNewState线程!在Java中我们解决了这个问题 在notifyAll()的帮助下,等待一点忙:

public synchronized void printNewState() {
    while (true) {
        while (!modified) {
            wait();
        }
        System.out.println(state);
        modified = false;
        **notify();** \\(?)
    }
}

public synchronized void setValue(int v) {
    while (modified) {
        wait();
    }
    state = v;
    notifyAll();
    modified = true;
    System.out.println("value set");
}

我不明白为什么通知也没有更改为notifyAll()?可能无法保证此通知转到setValue(int)???的线程

谢谢

1 个答案:

答案 0 :(得分:0)

notify()方法唤醒一个等待线程,而notifyAll()方法唤醒所有等待线程。问题是,使用notify()时,被唤醒的线程实际上是随机的。

如果某个其他线程意外或恶意wait()在同一个对象上,它可能会收到通知,而不是您希望唤醒的线程。

请查看this answer以获取更多信息。对这个答案的评论也很有意思。

修改

在您发布的代码示例中,notify()中的第一个printNewState()一次只能处理一个更新,因此通知所有等等没有意义发布更新的主题。但是,代码假定只有调用setValue(int)的线程正在等待。

由于public synchronized void setValue(int)基本上与将synchronized(this)作为方法的第一行相同,因此实际上并未保证。任何引用C类实例的代码都可以等待并搞砸代码。

同步和等待/通知操作应在对象锁定/监视器上发生。 private final Object monitor = new Object()synchronized(this.monitor)this.monitor.wait()this.monitor.notifyAll()等。

我还要注意modified = true需要放在notifyAll() setValue(int)之前,否则其他等待更新线程将在没有printNewState()注意到更新的情况下继续进行。< / p>

另外,private boolean modified应该是private volatile boolean modified,而private int state也是如此,尽管AtomicInteger可能是更好的选择。