title: Producer Consumer scenario with Reentrant Lock and Condition in Java
body: <p>I have written a Producer Consumer program using Reentrant Lock and condition. It is working correctly, but I am not very sure whether implementation is correct. Moreover it does not seem to be optimal. Can somebody please verify if this is a correct implementation, moreover can you please tell, how to optimize it, like - taking lock at the place where it is really required</p>
  
  <pre><code>public class TestRL {
  
  static class Observed {
      boolean filled = false;
  
      public void setFilled(boolean filled) {
          this.filled = filled;
      }
  
      public boolean getFilled() {
          return filled;
      }
  }
  
  static Observed observed = new Observed();
  
  static class Consumer implements Runnable {
      Observed observed;
      ReentrantLock lock;
      Condition condition;
  
      Consumer(Observed observed, ReentrantLock lock, Condition condition) {
          this.observed = observed;
          this.lock = lock;
          this.condition = condition;
      }
  
      @Override
      public void run() {
          lock.lock();
          try {
              for (int i = 0; i &lt; 20; i++) {
                  if (observed.getFilled() == false) {
                      try {
                          System.out.println("consumer waiting");
                          condition.await();
                          System.out.println("consumed");
  
                          Thread.sleep(400 + 1000 * i % 2);
                      } catch (InterruptedException e1) {
                          e1.printStackTrace();
                      }
                      observed.setFilled(false);
                      condition.signalAll();
                  }else{
                      observed.setFilled(false);
                      condition.signalAll();
                  }
              }
          } finally {
              lock.unlock();
          }
  
      }
  }
  
  static class Producer implements Runnable {
      Observed observed;
      ReentrantLock lock;
      Condition condition;
  
      Producer(Observed observed, ReentrantLock lock, Condition condition) {
          this.observed = observed;
          this.lock = lock;
          this.condition = condition;
      }
  
      @Override
      public void run() {
          lock.lock();
          try {
              for (int i = 0; i &lt; 20; i++) {
                  if (observed.getFilled() == true) {
                      try {
                          System.out.println("producer waiting");
                          condition.await();
                          System.out.println("produced");
                          Thread.sleep(1000);
                      } catch (InterruptedException e1) {
                          e1.printStackTrace();
                      }
                      observed.setFilled(true);
                      condition.signalAll();
                  }else{
                      observed.setFilled(true);
                      condition.signalAll();
                  }
              }
          } finally {
              lock.unlock();
          }
  
      }
  }
  
  /**
   * @param args
   */
  public static void main(String[] args) {
      ReentrantLock lock = new ReentrantLock();
      Condition condition = lock.newCondition();
      Producer producer = new Producer(observed, lock, condition);
      Consumer consumer = new Consumer(observed, lock, condition);
      Thread t1 = new Thread(producer);
      Thread t2 = new Thread(consumer);
      t1.start();
      t2.start();
  
  }
  </code></pre>
  
  <p>}</p>