简体   繁体   English

为什么有时在生产者-消费者问题的输出中,消费者得到的是以前的值,而不是生产者产生的新值?

[英]Why sometimes in the output of the producer-consumer problem, the consumer is getting a previous value instead of the new value produced by producer?

I have this below Java code:我有下面的 Java 代码:

class Q2 {
    int n;
    boolean valueSet = false;

    synchronized int get() {
        while(!valueSet)
            try {
                System.out.println("Consumer waiting ...");
                wait();
            }
            catch(InterruptedException e) {
                System.err.println("InterruptedException caught");
            }
        System.out.println("Consumer awakened");
        System.out.println("Got: "+n);
        valueSet = false;
        notify();
        System.out.println("Consumer called notify()");
        return n;
    }

    synchronized void put(int n) {
        while(valueSet)
            try {
                System.out.println("Producer waiting ...");
                wait();
            }
            catch(InterruptedException e) {
                System.err.println("InterruptedException caught");
            }
        System.out.println("Producer awakened");
        System.out.println("Before put n is: " + this.n);
        this.n = n;
        valueSet = true;
        System.out.println("Put: " + this.n);
        notify();
        System.out.println("Producer called notify()");
    }
}

class Producer2 implements Runnable {
    Q2 q;
    int noOfTimes;

    Producer2(Q2 q) {
        this.q = q;
        new Thread(this, "Producer").start();
    }

    public void run() {
        int i=0;
        noOfTimes=0;
        while(q.n < 2) {
            q.put(i++);
            noOfTimes++;
        }
        System.out.println("Producer ran: " + noOfTimes + " times.");
    }
}

class Consumer2 implements Runnable {
    Q2 q;
    int noOfTimes;

    Consumer2(Q2 q) {
        this.q = q;
        new Thread(this, "Consumer").start();
    }

    public void run() {
        int i=0;
        noOfTimes=0;
        while(q.n < 2) {
            System.out.println("Iteration " + (noOfTimes+1) + "; Before get() n is: " + q.n);
            int val = q.get();
            System.out.println("After get() n is: " + q.n);
            noOfTimes++;
        }
        System.out.println("Consumer ran: " + noOfTimes + " times.");
        System.out.println("n: " + q.n);
    }
}

public class PCFixed {

    public static void main(String[] args) {
        Q2 q = new Q2();
        new Producer2(q);
        new Consumer2(q); 
    }
}

One particular output:一个特定的输出:

Producer awakened
Before put n is: 0 // because n is int and default value of n is 0
Put: 0 // instance variable n associated with object of Q2 is set to 0
Producer called notify() // no effect
Producer waiting ... // thread spawned from Producer waits
Iteration 1; Before get() n is: 0 // context switching to thread spawned from Consumer
Consumer awakened
Got: 0
Consumer called notify()
After get() n is: 0
Iteration 2; Before get() n is: 0
Producer awakened // context switching to Producer's thread
Before put n is: 0
Put: 1
Producer called notify()
Producer waiting ... // Producer's thread waits/sleeps
Consumer awakened // context switching to Consumer's thread
Got: 1
Consumer called notify()
After get() n is: 1
Producer awakened // context switching to Producer's thread
Before put n is: 1
Put: 2 // #### line 1
Producer called notify()
Iteration 3; Before get() n is: 1 // #### line 2: context switching to Consumer's thread
Producer ran: 3 times. // context switching to Producer's thread
Consumer awakened // context switching to Consumer's thread
Got: 2
Consumer called notify()
After get() n is: 2
Consumer ran: 3 times.
n: 2 // Consumer's thread ends here

Can someone help me understand why, in the above output, at line 2 the value of n fetched by consumer is 1 when the producer already produced a new value which is 2 at line 1?有人能帮我理解为什么在上面的输出中,当生产者已经在第 1 行产生了一个新值 2 时,在第 2 行消费者获取的n的值为 1 吗? Since the same instance of Q2 are being shared by both the Producer's and Consumer's thread why is the changed value of n not being reflected at line 2?由于Q2的同一个实例被生产者和消费者的线程共享,为什么n的更改值没有反映在第 2 行? Also please clarify me the meaning of a threaded object even though I know what a thread is?即使我知道线程是什么,也请澄清线程对象的含义?

And if you don't see this behavior on running once the above code run a few times and you will see such behavior.而且,如果您在运行时没有看到这种行为,那么一旦上面的代码运行几次,您就会看到这种行为。

Your read from qn in Consumer2::run is racy, ie it is executed concurrently with the write to qn in Q2::put .您在Consumer2::run中从qn读取的内容很活泼,即它与在Q2::put中对qn的写入同时执行。 As a result, it can read either the previous value or the currently written value of qn .因此,它可以读取qn的先前值或当前写入的值。 A possible solution is move the printing of "Before get() n is..." to under the lock.一个可能的解决方案是将“Before get() n is...”的打印移动到锁下。

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

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