2015-04-02 14 views
6

Ich bin sehr verwirrt über dieses Thema - ob das Lesen/Umschalten eines bool-Wertes Thread-sicher ist.C# und Thread-Sicherheit eines bool

// case one, nothing 
    private bool v1; 
    public bool V1 { get { return v1; } set { v1 = value; } } 

    // case two, with Interlocked on set 
    private int v2; 
    public int V2 { get { return v2; } set { Interlocked.Exchange(ref v2, value); } } 

    // case three, with lock on set 
    private object fieldLock = new object(); 
    private bool v3; 
    public bool V3 { get { return v3; } set { lock (fieldLock) v3 = value; } } 

Sind sie alle Thread-sicher?

EDIT

Von dem, was ich gelesen habe (click) Unteilbarkeit von Bool garantiert nicht, wird es Thread-sicher sein. Will dann volatile Hilfe eingeben?

+1

Keine von diesen sind thread-safe. Der Thread, der den Getter aufruft, liest immer einen veralteten Wert. Wie alt es ist, hängt vom Prozessor und vom Optimierer ab. Es reicht von wenigen Nanosekunden bis unendlich. Der Getter muss auch synchronisieren. Oder Sie würden ManualResetEvent/Slim verwenden. –

+0

@ Ksv3n * Zuweisung ist immer eine atomare Operation * Falsch, 'lange' (64 Bit) Zuweisung von einem 32-Bit-Programm ist nicht atomar. – xanatos

+0

@HansPassant Ein Getter kann einen alten Wert lesen, das ist verständlich. Wie könnte es jedoch bis ins Unendliche dauern? Wenn Sie eine Sperre verwenden, wird der * korrekte * Wert gelesen - lesen Sie ihn erneut, als wäre er flüchtig? Ich glaube nicht, dass es so funktioniert, ich bin verwirrt darüber, was du sagst. Ich dachte, dass, sobald niemand mehr schreibt, der Getter richtig funktioniert. –

Antwort

12

Nein, nicht alle von ihnen sind Thread-sicher.

Fall eins ist nicht wirklich völlig threadsicher, oder besser gesagt - es ist überhaupt nicht threadsicher. Selbst wenn Operationen mit Booleschen Werten atomar sind, kann der Variablenwert in einem Cache gespeichert werden, und so kann jeder Wert, wie in Multicore-CPUs, einen eigenen Cache haben, der Wert kann möglicherweise beschädigt sein.

Wenn Sie noch weiter gehen, können Compiler und CPU einige interne Optimierungen durchführen, einschließlich der Neuanordnung von Befehlen, was die Programmlogik beeinträchtigen kann.

Sie können das Schlüsselwort volatile hinzufügen, um den Compiler zu benachrichtigen, dass dieses Feld in einem Kontext mit mehreren Threads verwendet wird. Es behebt Probleme mit der Neuanordnung von Caches und Befehlen, gibt Ihnen aber keinen wirklich "threadsicheren" Code (da Schreiboperationen immer noch nicht synchronisiert sind). Auch volatile kann nicht auf lokale Variable angewendet werden.

Also, wenn Sie mit Multi-Threading zu tun haben, müssen Sie immer eine Technik der Thread-Synchronisation auf wertvolle Ressourcen verwenden.

Für weitere Informationen - lesen Sie this Antwort, die einige tiefere Erklärung der verschiedenen Techniken hat. (Beispiel gibt es etwa int, aber es ist nicht wirklich wichtig, beschreibt es allgemeine Vorgehensweise.)

+3

* Wert kann möglicherweise beschädigt werden * Nein, Wert kann nicht beschädigt werden (wie in "in illegalen/undefinierten Wert transformieren"). Sie könnten veraltete ("alte") Werte erhalten. – xanatos

+0

Ich meine "korrumpiert" in einer Weise "nicht eine, die es sein sollte oder Sie erwarten es zu sein". Definitiv keine Korruption im Sinne von Speicherkorruption :) – Yura