public class NoVisibility {
    
private static boolean ready;
    
private static int number;

    
private static class ReaderThread extends Thread {
        
public void run() {
            
while (ready)
                Thread.yield();
            System.out.println(number);
        }
    }

    
public static void main(String[] args) {
        
new ReaderThread().start();
        number 
= 42;
        ready 
= true;
    }
}

synchronized關(guān)鍵字除了用于保證代碼段的原子性外,另外一個非常重要的意義在于對于線程共享變量修改的可視。
We want not only to prevent one thread from modifying the state of an object when another is using it, but also to ensure that when a thread modifies the state of an object, other threads can actually see the changes that were made.But without synchronization, this may not happen.

When a thread reads a variable without synchronization, it may see a stale value, but at least it sees a value that was actually placed there by some thread rather than some random value.This safety guarantee is called out-ofthin- air safety. Out-of-thin-air safety applies to all variables, with one exception: 64-bit numeric variables (double and long) that are not declared volatile

結(jié)論:
Locking is not just about mutual exclusion; it is also about memory visibility. To ensure that all threads see the most up-to-date values of shared mutable variables, the reading and writing threads must synchronize on a common lock.
互斥并不是加鎖的唯一目的,還包含memory visibility。為了保證所有的線程能夠訪問到最新的共享變量的值,所有的讀寫共享變量的操作都需要對同一個對象加鎖以保證同步

from Java Concurrency in Practice  By Brian Goetz, Tim Peierls, Joshua Bloch, Joseph Bowbeer, David Holmes,
Doug Lea