Synchronizacja wątków(AutoResetEvent, ManualResetEvent, Interlocked), część 3

W celu synchronizacji wątków można wykorzystać mechanizm zdarzeń: ManualResetEvent oraz AutoResetEvent. Rozwiązanie polega na zastosowaniu sygnalizacji. Chcąc wejść do sekcji krytycznej piszemy:

ManualResetEvent resetEvent = new ManualResetEvent(false);
resetEvent.WaitOne();

W konstruktorze ustawiamy początkową wartość sygnału na false(brak sygnału). Następnie wywołujemy metodę WaitOne, która czeka na nadejście sygnału. Metoda blokuje kod aż  do momentu gdy w jakimś miejscu kodu zostanie wysłane zdarzenie za pomocą metody Set:

resetEvent.Set();

AutoResetEvent działa bardzo podobnie – jedyną różnicą jest fakt, że po otrzymaniu sygnału w WaitOne, stan zostaje ponownie ustawiony na false. Rozważmy dwa fragmenty kodu z ManualResetEvent oraz AutoResetEvent:

ManualResetEvent resetEvent = new ManualResetEvent(true);
resetEvent.WaitOne();
resetEvent.WaitOne();
MessageBox.Show("Hello world"); // zostanie wykonane

AutoResetEvent resetEvent = new AutoResetEvent(true);
resetEvent.WaitOne();            
resetEvent.WaitOne();
MessageBox.Show("Hello world"); // nigdy nie zostanie wykonane

W przypadku ManualResetEvent, WaitOne sprawdza tylko sygnał i nie modyfikuje go. Zatem wiadomość MessageBox zostanie wyświetlona. W przypadku AutoResetEvent, kod zostanie zablokowany na drugim wywołaniu WaitOne ponieważ  pierwsze wykonanie WaitOne ustawi sygnał na false.

Interlocked jest bardzo wydajnym narzędziem(statyczną klasą) umożliwiającym wykonywanie podstawowych operacji takich jak inkrementacja czy zamiana dwóch liczb w sposób atomowy czyli bezpieczny z punktu widzenia współbieżności. Konkretnie do dyspozycji mamy następujące metody:

Add

Dodanie dwóch liczb ze sobą.

CompareExchange

Porównanie ze sobą dwóch liczb i w przypadku gdy są one równe zastąpienie pierwszej z nich wartością dostarczoną w drugim parametrze.

Decrement

Zmniejszenie wartości o jeden.

Exchange

Zamiana wartości zmiennych.

Increment

Inkrementacja(zwiększenie o jeden).

Read

Przydatne na procesorach 32 bitowych gdzie operacje czytania zmiennych 64-bitowych nie jest atomowa.

Przykład użycia:

int value = 5;
Interlocked.Increment(ref value);
System.Diagnostics.Debug.Assert(value == 6);

W następnej, ostatniej części napiszę o kilku  nowościach w .NET 4.0, zapraszam.

3 thoughts on “Synchronizacja wątków(AutoResetEvent, ManualResetEvent, Interlocked), część 3”

  1. Pingback: rowne
  2. Bardzo prosty i zarazem genialny artykuł, bardzo pomógł mi podczas pisania wielu programów.
    Bardzo dziękuje i oby takich więcej! 🙂

Leave a Reply

Your email address will not be published.