Por que preciso de uma barreira de memória?
O C # 4 em poucas palavras (btw altamente recomendado) usa o código a seguir para demonstrar o conceito de MemoryBarrier (supondo que A e B foram executados em threads diferentes):
class Foo{
int _answer;
bool complete;
void A(){
_answer = 123;
Thread.MemoryBarrier(); // Barrier 1
_complete = true;
Thread.MemoryBarrier(); // Barrier 2
}
void B(){
Thread.MemoryBarrier(); // Barrier 3;
if(_complete){
Thread.MemoryBarrier(); // Barrier 4;
Console.WriteLine(_answer);
}
}
}
eles mencionam que as Barreiras 1 e 4 impedem que este exemplo escreva 0 e as Barreiras 2 e 3 fornecem umfrescura garantia: eles garantem que, se B correu atrás de A, lendo_completo avaliaria paraverdadeiro.
Eu realmente não estou entendendo. Acho que entendo por que as Barreiras 1 e 4 são necessárias: não queremos que a gravação seja_responda para ser otimizado e colocado após a gravação no_completo (Barreira 1) e precisamos garantir que_responda não é armazenado em cache (Barreira 4). Também acho que entendo por que a Barreira 3 é necessária: se A funcionou até pouco depois de escrever_complete = true, B ainda precisaria atualizar_completo para ler o valor certo.
Mas não entendo por que precisamos da Barreira 2! Parte de mim diz que é porque talvez o Thread 2 (execução B) já tenha sido executado até (mas não incluindo)if (_complete) e por isso precisamos garantir que_completo é atualizado.
No entanto, não vejo como isso ajuda. Ainda não é possível que_completo será definido como true em A, mas o método B verá uma versão em cache (falsa) de_completo? Ou seja, se o Thread 2 executou o método B até depois do primeiro MemoryBarrier e o Thread 1 executou o método A até_complete = true mas não mais, e o Thread 1 foi retomado e testadoif (_complete) - poderiaE se não resultar emfalso?