Por que o Java não vê o valor atualizado de outro encadeamento?

Veja este código (extraído do livro Effective Java)

import java.util.concurrent.TimeUnit;


public class Main {
private static boolean stopReq;
public static void main(String[] args) throws InterruptedException {


    Thread bgw = new Thread(new Runnable()
    {
        public void run(){

        int i = 0;
        while(!stopReq){ i++;}
        }
        });
    bgw.start();
    TimeUnit.SECONDS.sleep(1);
    stopReq = true;

}

}

Por que obgw thread ficar preso em um loop infinito? É o cache de sua própria cópia destopReq quando chegou ao loop? Portanto, ele nunca vê o valor atualizado do outro segmento?

Entendo que a solução para esse problema seria a sincronização ou uma variável volátil, mas estou curioso para saber por que essa implementação atual não funciona.

obrigado

questionAnswers(5)

yourAnswerToTheQuestion