413 Stimmen

Existieren Zombies ... in .NET?

Ich hatte eine Diskussion mit einem Teamkollegen über das Sperren in .NET. Er ist ein wirklich intelligenter Kerl mit langjähriger Erfahrung sowohl in der nieder- als auch in der höheren Programmierung, aber seine Erfahrung mit der niedrigeren Programmierung übertrifft meine bei weitem. Jedenfalls argumentierte er, dass das Sperren in .NET auf kritischen Systemen, die unter hoher Last stehen, wenn möglich vermieden werden sollte, um die zugegebenermaßen geringe Möglichkeit eines "Zombie-Threads" zu vermeiden, der ein System zum Absturz bringen könnte. Ich benutze regelmäßig das Sperren und wusste nicht, was ein "Zombie-Thread" war, also fragte ich nach. Der Eindruck, den ich aus seiner Erklärung gewonnen habe, ist, dass ein Zombie-Thread ein Thread ist, der beendet wurde, aber auf irgendwie noch einige Ressourcen festhält. Ein Beispiel, das er nannte, wie ein Zombie-Thread ein System zerstören könnte, war ein Thread, der nach dem Sperren eines Objekts einen bestimmten Vorgang startet und dann irgendwann vor der Freigabe des Sperre beendet wird. Diese Situation hat das Potenzial, das System zum Absturz zu bringen, weil schließlich Versuche, diese Methode auszuführen, dazu führen, dass die Threads alle darauf warten, Zugriff auf ein Objekt zu erhalten, das nie zurückgegeben wird, weil der Thread, der das gesperrte Objekt verwendet, tot ist.

Ich denke, ich habe das Wesentliche verstanden, aber falls ich daneben liege, lass es mich bitte wissen. Das Konzept erschien mir logisch. Ich war nicht vollständig überzeugt, dass dies tatsächlich in .NET passieren könnte. Ich habe zuvor nie von "Zombies" gehört, aber ich erkenne an, dass Programmierer, die in tieferen Ebenen gearbeitet haben, ein besseres Verständnis von Rechnergrundlagen (wie dem Threaden) haben. Ich sehe definitiv den Wert des Sperrens, habe aber auch viele erstklassige Programmierer gesehen, die das Sperren nutzen. Ich habe auch nur begrenzte Fähigkeit, dies für mich selbst zu bewerten, weil ich weiß, dass die lock(obj)-Anweisung nur ein syntaktischer Zucker für ist:

bool lockWasTaken = false;
var temp = obj;
try { Monitor.Enter(temp, ref lockWasTaken); { body } }
finally { if (lockWasTaken) Monitor.Exit(temp); }

und weil Monitor.Enter und Monitor.Exit als extern markiert sind. Es scheint vorstellbar, dass .NET eine Art Verarbeitung durchführt, die Threads vor der Exposition gegenüber Systemkomponenten schützt, die solche Auswirkungen haben könnten, aber das ist rein spekulativ und wahrscheinlich nur darauf zurückzuführen, dass ich noch nie von "Zombie-Threads" gehört habe. Daher hoffe ich, hier Feedback dazu zu bekommen:

  1. Gibt es eine klarere Definition eines "Zombie-Threads" als die, die ich hier erklärt habe?
  2. Können Zombie-Threads in .NET auftreten? (Warum/Warum nicht?)
  3. Falls zutreffend, wie könnte ich in .NET die Erstellung eines Zombie-Threads erzwingen?
  4. Falls zutreffend, wie kann ich das Sperren nutzen, ohne ein Szenario mit Zombie-Threads in .NET zu riskieren?

Aktualisierung

Ich habe diese Frage vor etwas mehr als zwei Jahren gestellt. Heute ist dies passiert:

Objekt befindet sich im Zombie-Zustand.

3voto

S.H. Punkte 2755

1. Gibt es eine klarere Definition eines "Zombie-Threads" als das, was ich hier erklärt habe?

Ich stimme zu, dass "Zombie-Threads" existieren. Es handelt sich um einen Begriff, der auf das verweist, was mit Threads passiert, die Ressourcen behalten, diese aber nicht freigeben und dennoch nicht vollständig sterben. Daher der Name "Zombie". Deine Erklärung dazu trifft ziemlich genau zu!

2. Können Zombie-Threads in .NET auftreten? (Warum/Warum nicht?)

Ja, sie können auftreten. Es ist eine Referenz, die tatsächlich von Windows als "Zombie" bezeichnet wird: MSDN verwendet das Wort "Zombie" für abgestorbene Prozesse/Threads

Dass dies häufig passiert, ist eine andere Sache und hängt von deinen Codierungstechniken und -praktiken ab. Wenn du jedoch gerne Thread-Locking machst und dies schon eine Weile getan hast, brauchst du dir darüber keine Sorgen zu machen, dass dieses Szenario bei dir auftritt.

Und ja, wie @KevinPanko in den Kommentaren richtig erwähnt hat, stammen "Zombie-Threads" aus Unix, weshalb sie in XCode-ObjectiveC verwendet werden und als "NSZombie" bezeichnet werden, um Fehler zu finden. Sie verhalten sich ziemlich ähnlich... der einzige Unterschied besteht darin, dass ein Objekt, das sterben sollte, zu einem "ZombieObjekt" für die Fehlersuche wird, anstatt dass der "Zombie-Thread" ein potentielles Problem in deinem Code darstellt.

0voto

Joshua Punkte 37898

Ich kann leicht genug Zombie-Threads erstellen.

var zombies = new List();
while(true)
{
    var th = new Thread(()=>{});
    th.Start();
    zombies.Add(th);
}

Dies führt die Thread-Handles (für Join()) aus. Es ist nur ein weiterer Speicherleckaspekt, soweit wir in der verwalteten Welt besorgt sind.

Nun gut, das Töten eines Threads auf eine Weise, dass er tatsächlich Sperren hält, ist eine Schmerzaktion, aber möglich. Der andere Kerl ExitThread() erledigt die Aufgabe. Wie er herausfand, wurde der Datei-Handle vom GC aufgeräumt, aber ein lock um ein Objekt herum würde nicht aufgeräumt. Aber warum würdest du das tun?

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X