Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 条件不成立时线程唤醒的混淆原因_Java_Multithreading_Concurrency - Fatal编程技术网

Java 条件不成立时线程唤醒的混淆原因

Java 条件不成立时线程唤醒的混淆原因,java,multithreading,concurrency,Java,Multithreading,Concurrency,我目前正在阅读有效Java,我在并发一章。在解释当一个条件不成立时线程可能会被唤醒的原因(While循环中wait()调用的条件)时,有一个原因让我非常困惑,我似乎无法理解 另一个线程可能已经获得了锁,并在线程调用notify和等待线程唤醒之间更改了保护状态 有人能解释一下这个句子吗?这是最容易用一个例子来解释的: public class ConditionTest implements Runnable { private boolean flag; pu

我目前正在阅读有效Java,我在并发一章。在解释当一个条件不成立时线程可能会被唤醒的原因(While循环中wait()调用的条件)时,有一个原因让我非常困惑,我似乎无法理解

另一个线程可能已经获得了锁,并在线程调用notify和等待线程唤醒之间更改了保护状态


有人能解释一下这个句子吗?

这是最容易用一个例子来解释的:

public class ConditionTest implements Runnable {
    
    private boolean flag;
    
    public void run() {
        try {
            synchronized (this) {
                while (true) {
                    this.wait();
                    if (flag) {
                        System.out.printf("%s: my condition is true\n",
                                          Thread.currentThread().getName());
                        flag = false;
                    } else {
                        System.out.printf("%s: my condition is false!!\n",
                                          Thread.currentThread().getName());
                    }
                }
            }
        } catch (InterruptedException ex) {
             // bail out
        }
    }
    
    public static void main(String[] args) throws InterruptedException {
        ConditionTest ct = new ConditionTest();
        new Thread(ct).start();
        new Thread(ct).start();
        new Thread(ct).start();
    
        Thread.sleep(1000);
    
        while (true) {
            synchronized(ct) {
                ct.flag = true;
                ct.notifyAll();
            }
            Thread.sleep(1000);
        }
    }
}
本例中的条件是runnable的
标志
应为
true
。工作线程报告条件的状态,然后清除标志

如您所见,main方法创建并启动了三个共享runnable的线程。然后,它重复将标志设置为true并通知工人

当工作人员被唤醒时,它可能会发现该标志为
false
;i、 它的状况不成立。事实上,如果您运行上述代码,您将看到三次中有两次发生这种情况

为什么?

因为,如果工作程序看到
标志==true
,它将清除该标志!所以当其他工人醒来时,他们看到了被清除的旗帜

这就是引用的文本所谈论的那种事情

诚然,在这种情况下,它是由我们可疑的
notifyAll
调用引起的,但一般原则适用。你应该检查一下情况



在某些平台上也可能(或曾经)发生虚假通知;i、 e.不是来自应用程序代码的任何
notify
notifyAll
调用的结果的通知。

这是最容易用一个示例解释的:

public class ConditionTest implements Runnable {
    
    private boolean flag;
    
    public void run() {
        try {
            synchronized (this) {
                while (true) {
                    this.wait();
                    if (flag) {
                        System.out.printf("%s: my condition is true\n",
                                          Thread.currentThread().getName());
                        flag = false;
                    } else {
                        System.out.printf("%s: my condition is false!!\n",
                                          Thread.currentThread().getName());
                    }
                }
            }
        } catch (InterruptedException ex) {
             // bail out
        }
    }
    
    public static void main(String[] args) throws InterruptedException {
        ConditionTest ct = new ConditionTest();
        new Thread(ct).start();
        new Thread(ct).start();
        new Thread(ct).start();
    
        Thread.sleep(1000);
    
        while (true) {
            synchronized(ct) {
                ct.flag = true;
                ct.notifyAll();
            }
            Thread.sleep(1000);
        }
    }
}
本例中的条件是runnable的
标志
应为
true
。工作线程报告条件的状态,然后清除标志

如您所见,main方法创建并启动了三个共享runnable的线程。然后,它重复将标志设置为true并通知工人

当工作人员被唤醒时,它可能会发现该标志为
false
;i、 它的状况不成立。事实上,如果您运行上述代码,您将看到三次中有两次发生这种情况

为什么?

因为,如果工作程序看到
标志==true
,它将清除该标志!所以当其他工人醒来时,他们看到了被清除的旗帜

这就是引用的文本所谈论的那种事情

诚然,在这种情况下,它是由我们可疑的
notifyAll
调用引起的,但一般原则适用。你应该检查一下情况


在某些平台上也可能(或曾经)发生虚假通知;i、 e.不是来自应用程序代码的任何
notify
notifyAll
调用的结果的通知