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
volatileantes 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.