Synchronizacja wątków w Javie

2007-12-07 23:55

Deweloperzy programujący wielowątkowo zapewne znają klasyczne typy wykorzystywanych przy okazji obiektów. Są to na przykład semafory, sekcje krytyczne (zwane też semaforami binarnymi) czy zdarzenia (events). Wszystkie one służą oczywiście do synchronizacji wątków tak, aby wykluczyć jednoczesny, wykluczający się dostęp do jednego zasobu.

Tego typu obiekty są wykorzystywane jednak głównie wtedy, kiedy mechanizm wątków jest zrealizowany w sposób specyficzny dla systemu operacyjnego – jak choćby poprzez API z Windows lub bibliotekę pthreads z Linuxa. Jeśli jednak mamy szczęście pracować z językiem, którego wielowątkowość jest częścią, wówczas korzysta się zwykle z nieco innych technik.
Taka sytuacja jest na przykład w Javie. Tam każdy obiekt (czyli instancja klasy dziedziczącej z java.lang.Object) może być użyty jako obiekt synchronizujący. Z grubsza działa to w ten sposób, że gdy jeden z wątków zadeklaruje wykorzystanie danego obiektu – przy pomocy słowa kluczowego synchronized – pozostałe nie mogą zrobić tego samego. Taka synchronizacja może odbywać się na wiele (składniowych) sposobów, jak choćby zadeklarowanie całej metody jak synchronizowanej:

  1. class SynchronizedCounter
  2. {
  3.    private int value = 0;
  4.    public synchronized int increment() { return ++value; }
  5. }

W tym prościutkim przykładzie mamy zagwarantowane, że żaden postronny wątek nie wtrąci się w operację inkrementacji ze zwróceniem wartości (która nie jest atomowa) i stan licznika będzie zawsze poprawny.
Tak więc mamy semafory tudzież sekcje krytyczne. A co np. ze zdarzeniami (sygnałami)? Otóż każdy obiekt posiada metody wait i notify, umożliwiające czekanie na powiadomienie z innego wątku i oczywiście wysłanie takiego powiadomienia. Całkiem skuteczne i dosyć proste; naturalnie na tyle, na ile proste może być programowanie wielowątkowe :)

Ale czy oryginalne? Otóż dziwnym trafem na platformie .NET cała sprawa wygląda niemal dokładnie tak samo :) Odwzorowania przytoczonych elementów Javy w C# to odpowiednio: lock (z dokładnością do kilku niuansów), Monitor.Wait i Monitor.Pulse. Sam sposób tworzenia wątków jest zresztą też bardzo bardzo podobny.
Wszelka zbieżność przypadkowa? Zdecydowanie nie. Lecz dobre rozwiązania warto jest przecież rozpowszechniać :]

Tags: , ,
Author: Xion, posted under Programming »


2 comments for post “Synchronizacja wątków w Javie”.
  1. Reg:
    December 8th, 2007 o 13:58

    To nie jest zbieżność tylko dlatego, że MS podprowadził rozwiązania z Javy, ale też dlatego, że monitor to powszechnie znany idiom mający swoje podwaliny w teorii programowania równoległego.

    Ciekawe jest też, że Windows API ma inne prymitywy do wielowątkowości niż Linux pthreads. Ten pierwszy ma sekcje krytyczne / muteksy i eventy (plus różne inne), ten drugi muteksy i zmienne warunkowe (conditional variables). Ja w swoim CommonLib zrobiłem jedne za pomocą drugich, tak że każde są dostępne na obydwu systemach :)

  2. Xion:
    December 8th, 2007 o 14:35

    Monitor to faktycznie zen wielowątkowości, ale ma tę wadę, że bez wsparcia od strony samego języka chyba niemożliwe jest jego zaimplementowanie. Dlatego część programistów może być przyzwyczajona do tych bardziej ‘klasycznych’ mechanizmów synchronizacji i przestawianie się na monitory może być nieco trudne. Nie zaszkodziłoby więc, że by sekcje krytyczne itp. były też w Javie czy .NET (chociaż oczywiście można je samemu napisać przy użyciu monitora).

    A co do tych różnic, to Windows API ma chyba lekki przerost formy nad treścią :) pthreads jest nieco skromniejszy, chociaż przypominam sobie, że ma też zwykłe (niebinarne) semafory. Jak zresztą jednak zauważyłeś, jedne obiekty można zaimplementować za pomocą drugich.

Comments are disabled.
 


© 2019 Karol Kuczmarski "Xion". Layout by Urszulka. Powered by WordPress with QuickLaTeX.com.