Digamos que es un recolector de basura de marcado y barrido concurrente.
Cuando dicho GC maneja punteros constantes, simplemente los recorre (comenzando desde las raíces) y marca cada bloque de datos encontrado. Luego barre todo sin marcar. Un código de cliente debe marcar los bloques de datos que usa como raíces.
¿Pero qué hacer con las variables? Aquí hay una situación:
V
es una variable que almacena un puntero al objetoA
.Thread 1
leeV
y suspende.Thread 2
modificaV
y hace que apunte al objetoB
.- El recolector de basura ejecuta su fase de "marca" y encuentra que
A
ya no se hace referencia, luego lo desasigna durante la fase de "barrido". Thread 1
despierta e intenta usarA
(ya leyóV
en el paso 2) marcándolo como root. Y falla , porqueA
ya no existe.
Entonces, ¿cómo manejar esto?
El Thread 2
puede marcar el objeto reemplazado A
con una bandera especial do-no-remove (bandera similar se utiliza para objetos recién asignados). ¿Pero cuándo se debe eliminar esta bandera? Por supuesto que Thread 1
podría hacer eso. Pero Thread 2
no sabe nada Thread 1
y, por lo tanto, no puedo estar seguro de que esto se haga nunca. Esto puede llevar a A
que nunca se libere. Y si GC eliminará esa bandera, entonces nada impide que A
se elimine cuando GC se ejecute por segunda vez ...
Las descripciones del recolector de basura de marca y barrido sobre la marcha que he leído solo mencionan que el objeto reemplazado debe estar "atenuado". Pero sin ningún detalle. Un enlace a una descripción más detallada de la solución sería muy apreciado.