0

I'm doing a simple exercise to understand the concept of threads and synchronization. But I don't know whether the code is correct or not.

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();
    }
}

The answer I have is: false false false false false false

But it feels wrong. Isn't there a true value should come in the middle of the code?

ahrooran
  • 931
  • 1
  • 10
  • 25

2 Answers2

2

Change the while condition like below and look at the comments . With your current code producer never executes.

Why? because isBinFull set to false initially and set to false in consumer too

and inside your producer code

while (!isBinFull) wait (); 

will be never become false and keep waiting inside while loop.

Change the code like below

 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);
        }
    }
Shiva
  • 1,962
  • 2
  • 13
  • 31
1

using synchronised at method level itself makes sure only one thread executes at a time.
synchronised keyword takes lock on the object it is being called i.e. machine in your case and hence the code is not a proper implementation of producer-consumer problem.

swayamraina
  • 2,958
  • 26
  • 28
  • The wait() call releases the lock. You will get an IllegalMonitorException (I believe), if you try to call wait() in a method not marked as synchronized. – Troels Feb 12 '20 at 19:10