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:
V
ist eine Variable, die einen Zeiger auf ein Objekt speichertA
.Thread 1
liestV
und suspendiert.Thread 2
ändertV
und zeigt auf das ObjektB
.- Der Garbage Collector führt seine "Mark" -Phase aus und trifft auf Begegnungen, auf die
A
nicht mehr verwiesen wird. Anschließend wird die Zuordnung während der "Sweep" -Phase aufgehoben. Thread 1
erwacht und versucht zu verwendenA
(bereits ausV
Schritt 2 gelesen ), indem es als root markiert wird. Und scheitert , weilA
es nicht mehr existiert.
Wie geht man damit um?
Das Thread 2
kann das ersetzte Objekt A
mit 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 1
könnte ich natürlich tun. Aber Thread 2
nichts weiß Thread 1
, und somit nicht sicher sein kann , dass dies jemals geschehen wird. Dies kann dazu führen, A
dass niemals befreit wird. Und wenn GC dieses Flag entfernt, verhindert nichts, dass A
es 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.