Diciamo che è un garbage collector simultaneo mark-and-sweep.
Quando tale GC gestisce puntatori costanti, li attraversa (iniziando dalle radici) e contrassegna tutti i blocchi di dati rilevati. Quindi spazza tutto senza segno. Un codice client deve contrassegnare i blocchi di dati che utilizza come root.
Ma cosa fare con le variabili? Ecco una situazione:
-
V
è una variabile, che memorizza un puntatore all'oggettoA
. -
Thread 1
leggeV
e sospende. -
Thread 2
modificaV
e fa puntare all'oggettoB
. - Il garbage collector esegue la sua fase di "mark" e rileva che
A
non viene più referenziato, quindi lo rilascia durante la fase di "sweep". -
Thread 1
si sveglia e tenta di utilizzareA
(già letto daV
al passaggio 2) contrassegnandolo come root. E fallisce , perchéA
non esiste più.
Quindi, come gestirlo?
Il Thread 2
può contrassegnare l'oggetto sostituito A
con uno speciale flag di non rimozione (il flag simile è usato per gli oggetti appena assegnati). Ma quando questa bandiera dovrebbe essere rimossa? Ovviamente Thread 1
potrebbe farlo. Ma Thread 2
non sa nulla di Thread 1
, e quindi non può essere sicuro che questo verrà fatto sempre. Questo potrebbe portare a A
non verrà mai liberato. E se GC rimuoverà quel contrassegno, nulla impedisce che A
venga rimosso quando GC viene eseguito per la seconda volta ...
Le descrizioni dei garbage collector mark-and-sweep al volo che ho letto ricordano solo che l'oggetto sostituito dovrebbe essere "grigio". Ma senza dettagli. Un link ad una descrizione più dettagliata della soluzione sarebbe molto apprezzato.