2015-04-02 16 views
6

Jestem bardzo zdezorientowany tym tematem - czy odczyt/przełączenie wartości bool jest bezpieczne dla wątków.C# i bezpieczeństwo wątku 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; } } 

Czy wszystkie z nich są bezpieczne dla wątków?

EDIT

Z tego co czytałem (click) niepodzielność z bool nie gwarantuje będzie bezpieczeństwo wątków. Czy wtedy będzie pomocny typ volatile?

+1

Żadne z nich nie jest bezpieczne dla wątków. Wątek, który wywołuje getter, zawsze odczytuje nieaktualną wartość. Jak nieaktualne jest to zależy od procesora i optymalizatora. Zakres od kilku nanosekund do nieskończoności. Program pobierający również musi zsynchronizować. Lub możesz użyć ManualResetEvent/Slim. –

+0

@ Ksv3n * Przypisanie zawsze jest operacją atomową * Fałszywe, 'długie' (64-bitowe) przypisanie przez program 32-bitowy nie jest atomowe. – xanatos

+0

@HansPassant Getter może odczytać starą wartość, jest to zrozumiałe. Jak jednak może trwać w nieskończoności? Użycie blokady sprawi, że odczyta ona * poprawną * wartość - ponownie odczyta ją tak, jakby była niestabilna? Nie sądzę, że to działa w ten sposób, jestem zdezorientowany tym, co mówisz. Myślałem, że gdy nikt już nie będzie pisać, getter będzie działał poprawnie. –

Odpowiedz

12

Nie, nie wszystkie z nich są bezpieczne dla wątków.

Sprawa pierwsza nie jest w rzeczywistości całkowicie bezpieczna dla wątków lub lepiej mówiąc - w ogóle nie jest bezpieczna dla wątków. Nawet jeśli operacje z wartościami logicznymi są atomowe, wartość zmienna może być przechowywana w pamięci podręcznej, a więc, tak jak w procesorze wielordzeniowym, każdy rdzeń ma własną pamięć podręczną, wartość może być potencjalnie uszkodzona.

Idąc dalej, kompilator i procesor mogą wykonywać pewne wewnętrzne optymalizacje, w tym zmianę kolejności instrukcji, co może mieć szkodliwy wpływ na logikę programu. Można dodać słowo kluczowe volatile, aby powiadomić kompilator, że to pole jest używane w kontekście wielowątkowym. Naprawi problemy z buforowaniem i zmianą kolejności instrukcji, ale nie da ci naprawdę "wątku bezpiecznego" kodu (ponieważ operacje zapisu nadal nie będą zsynchronizowane). Również volatile nie można zastosować do zmiennej lokalnej.

W przypadku wielowątkowości zawsze trzeba zastosować technikę synchronizacji wątku na wartościowych zasobach.

Aby uzyskać więcej informacji, przeczytaj odpowiedź this, która zawiera szczegółowe objaśnienia różnych technik. (przykład jest około int, ale tak naprawdę nie ma znaczenia, opisuje ogólne podejście.)

+3

* wartość może być potencjalnie uszkodzona * Nie, wartość nie może być uszkodzona (jak w "transform w nielegalnej/niezdefiniowanej wartości"). Możesz uzyskać nieaktualne ("stare") wartości. – xanatos

+0

Mam na myśli "uszkodzony" w pewnym sensie "nie jeden, taki powinien być lub ty się tego spodziewasz". Zdecydowanie nie jest uszkodzony w sensie korupcji pamięci :) – Yura

Powiązane problemy