title: Why is `synchronized (new Object()) {}` a no-op?
body: <p>In the following code:</p>
  
  <pre class="lang-java prettyprint-override"><code>class A {
      private int number;
  
      public void a() {
          number = 5;
      }
  
      public void b() {
          while(number == 0) {
              // ...
          }
      }
  }
  </code></pre>
  
  <p>If method b is called and then a new thread is started which fires method a, then method b is not guaranteed to ever see the change of <code>number</code> and thus <code>b</code> may never terminate.</p>
  
  <p>Of course we could make <code>number</code> <code>volatile</code> to resolve this. However for academic reasons let's assume that <code>volatile</code> is not an option:</p>
  
  <p>The <a href="http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html#synchronization" rel="noreferrer">JSR-133 FAQs</a> tells us:</p>
  
  <blockquote>
    <p>After we exit a synchronized block, we release the monitor, which <strong>has the effect of flushing the cache to main memory</strong>, so that writes made by this thread can be visible to other threads. Before we can enter a synchronized block, we acquire the monitor, which <strong>has the effect of invalidating the local processor cache</strong> so that variables will be reloaded from main memory.</p>
  </blockquote>
  
  <p>This sounds like I just need both <code>a</code> and <code>b</code> to enter and exit any <code>synchronized</code>-Block at all, no matter what monitor they use. More precisely it sounds like this...:</p>
  
  <pre class="lang-java prettyprint-override"><code>class A {
      private int number;
  
      public void a() {
          number = 5;
          synchronized(new Object()) {}
      }
  
      public void b() {
          while(number == 0) {
              // ...
              synchronized(new Object()) {}
          }
      }
  }
  </code></pre>
  
  <p>...would eliminate the problem and will guarantee that <code>b</code> will see the change to <code>a</code> and thus will also eventually terminate.</p>
  
  <p>However the FAQs also clearly state:</p>
  
  <blockquote>
    <p>Another implication is that the following pattern, which some people
    use to force a memory barrier, doesn't work:</p>
  
  <pre><code>synchronized (new Object()) {}
  </code></pre>
    
    <p>This is actually a no-op, and your compiler can remove it entirely,
    because the compiler knows that no other thread will synchronize on
    the same monitor. You have to set up a happens-before relationship for
    one thread to see the results of another.</p>
  </blockquote>
  
  <p>Now that is confusing. I thought that the synchronized-Statement will cause caches to flush. It surely can't flush a cache to main memory in way that the changes in the main memory can only be seen by threads which synchronize on the same monitor, especially since for volatile which basically does the same thing we don't even need a monitor, or am I mistaken there? So why is this a no-op and does not cause <code>b</code> to terminate by guarantee?</p>