同步和线程练习

时间:2018-11-18 06:20:51

标签: java synchronized producer-consumer

我正在做一个简单的练习来理解线程和同步的概念。但是我不知道代码是否正确。

public class PopcornMachine {

    // shared resource
    private boolean isBinFull = false; 

    // producer method
    public synchronized void placePopcorn () throws InterruptedException { 
        while (true) {
            while (!isBinFull) wait ();
            isBinFull = true;
            System.out.println(isBinFull);
            notify ();
            Thread.sleep(1000);
        }
    }

    // consumer code
    public synchronized void takePopcorn () throws InterruptedException {
        while (true) {
            while (isBinFull) wait ();
            isBinFull = false;
            System.out.println(isBinFull);
            notify ();
            Thread.sleep(1000);
        }
    }
}

public class PopcornDemo {
    public static void main (String[] args) throws InterruptedException{
        final PopcornMachine machine = new PopcornMachine();

        Thread produce = new Thread (new Runnable() { 
            public void run() { 
                try { 
                    machine.placePopcorn (); 
                } catch(InterruptedException e) {}                 
            }
        }); 

        Thread consume = new Thread (new Runnable() { 
            public void run() { 
                try { 
                    machine.takePopcorn (); 
                } catch(InterruptedException e) {} 
            }
        }); 

        produce.start();
        consume.start();

        produce.join();
        consume.join();
    }
}

我的答案是: 假 假 假 假 假 错误

但是感觉不对。代码中间不应该有一个真正的价值吗?

2 个答案:

答案 0 :(得分:2)

按如下所示更改while条件并查看注释。使用您当前的代码生产者将永远不会执行。

为什么?因为isBinFull最初也设置为false,而在消费者中也设置为

并在生产者代码中

while (!isBinFull) wait (); 

将永远不会成为false并在while循环内一直等待。

按如下所示更改代码

 public synchronized void placePopcorn () throws InterruptedException { 
        while (true) {
            while (isBinFull) wait(); //Look here, waiting since bin is full
            isBinFull = true;
            System.out.println(Thread.currentThread().getName() + ":"+isBinFull);
            notifyAll ();
            Thread.sleep(500);
        }
    }

    // consumer code
    public synchronized void takePopcorn () throws InterruptedException {
        while (true) {
            while (!isBinFull) wait(); ////Look here, waiting since bin is not full
            isBinFull = false;
            System.out.println(Thread.currentThread().getName() + ":"+isBinFull);
            notifyAll ();
            Thread.sleep(500);
        }
    }

答案 1 :(得分:1)

在方法级别本身使用synchronised可以确保一次仅执行一个线程。
synchronised关键字在要调用的对象上带有lock,在您的情况下为machine,因此代码不是生产者-消费者问题的正确实现。