2014-03-12 17 views
8

Ich habe über Einfädeln dieses Buch von Joseph Albahari lesen:
http://www.albahari.com/threading/Warum ist diese Zuweisung nicht Thread-sicher?

In Teil 2, fand ich dieses Beispiel:
http://www.albahari.com/threading/part2.aspx#_When_to_Lock

Hier ist das bereits erwähnte Beispiel:

class ThreadUnsafe 
{ 
    static int _x; 
    static void Increment() { _x++; } 
    static void Assign() { _x = 123; } 
} 

Gewindesichere Version:

class ThreadSafe 
{ 
    static readonly object _locker = new object(); 
    static int _x; 

    static void Increment() { lock (_locker) _x++; } 
    static void Assign() { lock (_locker) _x = 123; } 
} 

Ich konnte nicht verstehen, warum Assign Methode ist nicht threadsicher. Sollte die Integer-Zuweisung nicht atomarer Betrieb auf 32- und 64-Bit-Architekturen sein?

Antwort

9

Die Zuweisung ist atomare darin, dass jeder Lese-Thread entweder 123 oder den vorherigen Wert sehen wird - nicht irgendein Zwischenwert. Es gibt jedoch keine Garantie, dass ein Thread den neuen Wert erst sehen kann, wenn zwei Speicherbarrieren vorhanden sind: eine Schreibspeicherbarriere im Schreib-Thread und eine Lesespeichersperre im Lese-Thread.

Wenn Sie hast zwei Threads wie folgt (nach _x öffentlichen oder internem machen, so dass sie von den anderen natürlich gelesen werden können - oder mit dem Code in der ThreadSafe Klasse sowieso):

// Thread 1 
Console.WriteLine("Writing thread starting"); 
ThreadSafe.Assign(); 
Console.WriteLine("Writing thread done"); 


// Thread 2 
Console.WriteLine("Reading thread starting"); 
while (ThreadSafe._x != 123) 
{ 
    // Do nothing 
} 
Console.WriteLine("Reading thread done"); 

. .. es gibt keine Garantie, dass Thread 2 jemals enden würde, weil Thread 2 die Zuweisung von Thread 1 möglicherweise nicht "sieht".

+0

Könnten Sie bitte diese while-Schleife erläutern? Wenn Thread 1 immer _x mit 123 belegt, was könnte Thread 2 dann davon lesen? – Ivan

+0

Der ursprüngliche Code hinzugefügt, um die Frage zu klären. –

+0

@Ivan: Was ist damit? Es versucht nur zu loopen, bis Thread 2 die Zuweisung von 123 zu "_x" "sieht". Der Punkt ist, dass es diese Veränderung vielleicht nie "sehen" wird. –