Nehmen wir an, es handelt sich um einen gleichzeitigen Mark-and-Sweep-Garbage-Collector.
Wenn ein solcher GC konstante Zeiger verarbeitet, geht er nur durch diese (ausgehend von den Wurzeln) und markiert jeden angetroffenen Datenblock. Dann fegt alles unmarkiert. Ein Client-Code sollte die Datenblöcke markieren, die er als Roots verwendet.
Aber was tun mit Variablen? Hier ist eine Situation:
Vist eine Variable, die einen Zeiger auf ein Objekt speichertA.Thread 1liestVund suspendiert.Thread 2ändertVund zeigt auf das ObjektB.- Der Garbage Collector führt seine "Mark" -Phase aus und trifft auf Begegnungen, auf die
Anicht mehr verwiesen wird. Anschließend wird die Zuordnung während der "Sweep" -Phase aufgehoben. Thread 1erwacht und versucht zu verwendenA(bereits ausVSchritt 2 gelesen ), indem es als root markiert wird. Und scheitert , weilAes nicht mehr existiert.
Wie geht man damit um?
Das Thread 2kann das ersetzte Objekt Amit einem speziellen Nicht-Entfernen-Flag markieren (ein ähnliches Flag wird für neu zugewiesene Objekte verwendet). Aber wann sollte diese Flagge entfernt werden? Das Thread 1könnte ich natürlich tun. Aber Thread 2nichts weiß Thread 1, und somit nicht sicher sein kann , dass dies jemals geschehen wird. Dies kann dazu führen, Adass niemals befreit wird. Und wenn GC dieses Flag entfernt, verhindert nichts, dass Aes entfernt wird, wenn GC zum zweiten Mal ausgeführt wird ...
Die spontanen Mark-and-Sweep-Garbage-Collector-Beschreibungen, die ich gelesen habe, erwähnen nur, dass das ersetzte Objekt "grau" sein sollte. Aber ohne Einzelheiten. Ein Link zu einer detaillierteren Beschreibung der Lösung wäre sehr willkommen.