Digamos que seja um coletor de lixo simultâneo de marcação e varredura.
Quando esse GC lida com ponteiros constantes, apenas os percorre (a partir das raízes) e marca todos os blocos de dados encontrados. Em seguida, varre tudo sem marcação. Um código de cliente deve marcar os blocos de dados que ele usa como raízes.
Mas o que fazer com variáveis? Aqui está uma situação:
V
é uma variável, que armazena um ponteiro para o objetoA
.Thread 1
lêV
e suspende.Thread 2
modificaV
e faz apontar para o objetoB
.- O coletor de lixo executa sua fase de "marcação" e encontra os que
A
não são mais referenciados, depois o desaloca durante a fase de "varredura". Thread 1
desperta e tenta usarA
(já lidoV
na etapa 2) marcando-o como root. E falha , porqueA
não existe mais.
Então, como lidar com isso?
O Thread 2
pode marcar o objeto substituído A
com um sinalizador especial de não remover (um sinalizador semelhante é usado para objetos alocados recentemente). Mas quando esse sinalizador deve ser removido? Claro que Thread 1
poderia fazer isso. Mas Thread 2
não sabe nada Thread 1
e, portanto, não pode ter certeza de que isso será feito sempre. Isso pode levar a A
nunca será liberado. E se o GC remover esse sinalizador, nada impede que ele A
seja removido quando o GC for executado pela segunda vez ...
As descrições rápidas e rápidas de coletores de lixo que li e lembrei de mencionar que o objeto substituído deve estar "acinzentado". Mas sem detalhes específicos. Um link para uma descrição mais detalhada da solução seria muito apreciado.