czwartek, 19 czerwca 2014

Wielowątkowość - Thread Safety

 Thread safety


Jeśli wiele wątków dostaje się/może się dostać do zmiennej stanu bez jakiejkolwiek synchronizacji to program nie będzie działał dobrze, aby tak się stało musi być zrobiona jedna z poniższych rzeczy:
  • zmienna stanu nie powinna być dostępna
  • zmienna stanu powinna być niezmienna (immutable)
  • powinno się użyć synchronizacji przy dostępie do zmiennej

Jak zdefiniować klasę która jest thread-safe?
Klasa taka działa dobrze kiedy jest dostępna/używana przez wiele wątków bez względu na przeplatanie się i harmonogram ich działania bez dodatkowej synchronizacji po stronie kodu wywołującego. Klasa taka zawiera wszystkie mechanizmy synchronizacji w sobie.

Klasy bez stanu są zawsze thread-safe.

Atomowość 

 

Problemem mogą być operacje złożone dla których mogą wystąpić race-conditions.
Dwa typy race-conditions:
  • check-then-act
  • read-modify-write
Przykłady race-conditions:
  • "singleton" class z niesynchronizowaną metodą getInstance()
  • niesynchronizowana operacja zwiększania licznika count++
Operacje A and B są wzajemnie do siebie atomowe jeśli z perspektywy wątku wykonującego A jeśli inny wątek wykonuje B to jest ona wykonana w całości albo w ogóle.

Blokowanie 

 

Klasa która ma jedną zmienną tworzącą stan może być thread safe jeśli zmienna jest atomowa (np AtomicLong), po dodaniu drugiej już tak nie musi być jeśli zmienne nie są niezależne. Aby zmiana zmiennych była atomowa należy zastosować blokowanie poprzez użycie bloków lub metod synchronized. Ten rodzaj blokad nazywa się intrinsic lock. Blokady te są wielo-wejściowe (reentrant) więc wątek może uzyskać dostęp do blokady ponownie jeśli już go ma.

Strzeżenie zmiennych blokadami


Aby złożone akcje (check-then-act, read-modify-write) były atomowe muszą się znaleźć w bloku synchronizowanym przez blokadę.

Dla każdej zmiennej do której może mieć dostęp wiele wątków wszystkie dostępy muszą być przeprowadzone z tą samą blokadą.

Dostęp do zmiennych powiązanych musi się odbywać na tej samej blokadzie.

Żywotność i wydajność

 

Należy zmniejszać bloki synchronizowane tylko na czas zmian zmiennych, nie należy w nich wykonywać długich operacji szczególnie tych związanych z siecią i dostępem do I/O.


Brak komentarzy:

Prześlij komentarz