Pular para conteúdo

Java Memory Model

O Java Memory Model (JMM) define quais escritas uma thread pode observar e quais reordenações preservam um comportamento válido. Apenas a ordem do código-fonte não cria visibilidade entre threads.

Happens-before

Se a ação A acontece antes da ação B (happens-before), os efeitos de A são visíveis a B e estão ordenados antes dela. As relações importantes incluem:

  • ordem do programa dentro de uma thread;
  • uma liberação antes de uma aquisição posterior do mesmo monitor;
  • uma escrita volatile antes de uma leitura posterior dessa variável;
  • ações anteriores a Thread.start() tornando-se visíveis à thread iniciada;
  • ações de uma thread tornando-se visíveis após um join() bem-sucedido;
  • transitividade da relação.

volatile não fornece atomicidade composta

private volatile boolean stopped;

void stop() {
    stopped = true;
}

void runLoop() {
    while (!stopped) doOneUnit();
}

volatile é adequado a um indicador independente de visibilidade. Ele não torna count++ atômico, pois o incremento é uma sequência de leitura, modificação e escrita. Use um lock ou uma classe atômica adequada para atualizações compostas.

Publicação segura

Um objeto deve ser publicado por uma relação happens-before antes que outras threads o utilizem. Locks, referências volatile, inicialização estática, coleções concorrentes e mecanismos de envio de tarefas podem estabelecer uma publicação segura segundo seus contratos. Campos final recebem garantias adicionais de inicialização quando o objeto não escapa durante a construção.

Regra de raciocínio

Não deduza o comportamento concorrente permitido a partir do que um processador ou uma execução de teste por acaso fez. Identifique o estado mutável compartilhado e o caminho happens-before de cada observação necessária.