title: java notify() does not release lock in for waiting object in a loop
body: <p>The problem is: there are two threads, one is a writer to a List another is a reader from the List. Sometimes reader gets stuck if loop in the writer has large amount of iterations. That reader in that case becomes Blocked (not Waiting), which means that it received notification, but writer did not released monitor?</p>
  
  <p>So, why so?
  What is the best to do with this? (is sleep fine?)</p>
  
  <pre><code>import java.util.LinkedList;
  import java.util.List;
  
  public class Main {
  
      private List&lt;Object&gt; m_calls =  new LinkedList&lt;Object&gt;();
  
      public void startAll(){
  
          Thread reader = new Thread(new Runnable() {           
              @Override
              public void run() {
                  while(true){
                      synchronized(m_calls){
                          while (m_calls.size() == 0) {
                              try {
                                  System.out.println("wait");
                                  m_calls.wait();
                              } catch (InterruptedException e) {                               
                                  return;
                              }
                          }
                          m_calls.remove(0);
                          System.out.println("remove first");
                      }
                  }
              }
          });
  
          Thread writer = new Thread(new Runnable() {           
              @Override
              public void run() {
  
                  for(int i = 0; i &lt; 15; i++){
  
                      // UN-comment to have more consistent behavior
                      /*try {
                          Thread.sleep(1);
                      } catch (InterruptedException e) {
                          // TODO Auto-generated catch block
                          e.printStackTrace();
                      }*/
                      synchronized(m_calls){
                          m_calls.add(new Object());
                          m_calls.notifyAll();
                          System.out.println("sent");
                      }
                  }
              }
          });
  
          reader.start();
          writer.start();
      }
  
      public static void main(String[] args) {     
          new Main().startAll();       
      } 
  }
  </code></pre>
  
  <p>Running of the code above gives different results:</p>
  
  <p>----------------------------------  1st attempt</p>
  
  <p>wait<br/>
  sent<br/>
  sent<br/>
  sent<br/>
  sent<br/>
  sent<br/>
  sent<br/>
  sent<br/>
  sent<br/>
  sent<br/>
  sent<br/>
  sent<br/>
  sent<br/>
  sent<br/>
  sent<br/>
  sent<br/>
  remove first<br/>
  remove first <br/>
  remove first<br/>
  remove first<br/>
  remove first<br/>
  remove first<br/>
  remove first<br/>
  remove first<br/>
  remove first<br/>
  remove first<br/>
  remove first<br/>
  remove first<br/>
  remove first<br/>
  remove first<br/>
  remove first<br/>
  wait<br/></p>
  
  <p>----------------------------------  2nd attempt</p>
  
  <p>wait<br/>
  sent<br/>
  sent<br/>
  sent<br/>
  sent<br/>
  sent<br/>
  sent<br/>
  remove first<br/>
  remove first<br/>
  remove first<br/>
  remove first<br/>
  remove first<br/>
  remove first<br/>
  wait<br/>
  sent<br/>
  sent<br/>
  remove first<br/>
  remove first<br/>
  wait<br/>
  sent<br/>
  sent<br/>
  sent<br/>
  sent<br/>
  sent<br/>
  sent<br/>
  sent<br/>
  remove first<br/>
  remove first<br/>
  remove first<br/>
  remove first<br/>
  remove first<br/>
  remove first<br/>
  remove first<br/>
  wait<br/></p>
  
  <p>------------------------------ Uncommented sleep() - works us expected</p>
  
  <p>wait<br/>
  sent<br/>
  remove first<br/>
  wait<br/>
  sent<br/>
  remove first<br/>
  wait<br/>
  sent<br/>
  remove first<br/>
  wait<br/>
  sent<br/>
  remove first<br/>
  wait<br/>
  sent<br/>
  remove first<br/>
  wait<br/>
  sent<br/>
  remove first<br/>
  wait<br/>
  sent<br/>
  remove first<br/>
  wait<br/>
  sent<br/>
  remove first<br/>
  wait<br/>
  sent<br/>
  remove first<br/>
  wait<br/>
  sent<br/>
  remove first
  wait<br/>
  sent<br/>
  remove first<br/>
  wait<br/>
  sent<br/>
  remove first<br/>
  wait<br/>
  sent<br/>
  remove first<br/>
  wait<br/>
  sent<br/>
  remove first<br/>
  wait<br/>
  sent<br/>
  remove first<br/>
  wait<br/></p>
  
  <p>Edit 1: The reader thread (one of them) seems to be not waiting any more, rather it's blocked, which looks like its monitor received notification (after notifyAll()) but writer thread do not release lock in its loop, what is confusing...</p>
  
  <p><img src="https://i.stack.imgur.com/puAqI.png" alt="enter image description here"></p>