Asynchroniczność kontra wątki

2008-03-10 23:02

Niekiedy trzeba zrobić coś czasochłonnego: operację, która nie zakończy się od razu, lecz zabierze zauważalny odcinek czasu. Dość często dotyczy to odczytu (lub zapisu) danych z miejsca, które nie musi być natychmiast dostępne: gniazdka sieciowego, międzyprocesowego potoku (pipe) czy w niektórych sytuacjach nawet pamięci dyskowej. Wówczas rzadko możemy pozwolić sobie na “powieszenie” programu na parę(naście/dziesiąt) sekund w oczekiwaniu, aż zlecona operacja się zakończy. W międzyczasie trzeba bowiem wykonywać też inne czynności, z aktualizacją interfejsu użytkownika na czele.

Typowy rozwiązaniem jest wtedy umieszczenie czasochłonnej czynności w osobnym wątku. Zdarza się jednak, że nie jest to jedyne wyjście. Niekiedy – na przykład przy korzystaniu z gniazd sieciowych w Windows API lub dowolnych strumieni w .NET – dysponujemy alternatywnym sposobem, którym jest zlecenie operacji asynchronicznej. Polega ono na żądaniu wykonania danego działania “w tle” wraz ze sposobem, w jaki chcemy odebrać informację zwrotną. W tym charakterze chyba najczęściej stosuje się funkcje typu callback, podawane – zależnie od języka – jako wskaźniki (C/C++), delegaci (Delphi, C#) lub obiekty implementujące ustalone interfejsy (Java). Po zakolejkowaniu takiego żądania program wykonuje się dalej bez żadnych przerw. Gdy zaś operacja zakończy się, nasz callback zostanie wywołany i w nim będzie można pobrać rezultaty zleconego zadania.
Brzmi całkiem nieźle, prawda? Właściwie można by powiedzieć, że to świetny sposób na uniknięcie stosowania tych strasznych wątków ;-) W praktyce trzeba jednak pamiętać o tym, że:

  • Brak wątków wcale nie oznacza, że nie wystąpią typowe dla wielowątkowości kłopoty – zwłaszcza problemy z synchronizacją dostępu do zasobów. Dotyczą one bowiem każdej sytuacji, kiedy to kod wykonujący się równoległe próbuje uzyskać dostęp do tych samych danych – niezależnie od tego, czy dotyczy to wątków, osobnych procesów ze współdzieloną pamięcią czy właśnie operacji asynchronicznych. Zresztą wewnątrz mechanizmu obsługi takich operacji równie dobrze siedzieć może zwyczajny wątek, który się nimi zajmuje w sposób przezroczysty.
  • Wywołania asynchroniczne “rozgałęziają” wykonywanie kodu w sposób bardziej subtelny (co oznacza: trudniejszy do śledzenia) niż wątki. W przypadku wątków zawsze dobrze widać miejsce rozpoczęcia i zakończenia pracy oraz całą te robotę, napisaną po kolei i w jednym miejscu. Jeśli zaś korzystamy z wywołań asynchronicznych, to kod obsługi wyniku operacji jest oddzielony od kodu, który tę operację zleca. To sprawia, że śledzenie i debugowanie może być trudniejsze i wymagać większej uwagi.

W sumie więc warto pamiętać o tym, że przy wprowadzaniu równoległości trzeba zawsze liczyć z dodatkowymi – nazwijmy to – “kwestiami do rozważenia” :] Unikanie tworzenia wątków za wszelką cenę nie musi zatem być najlepszym wyjściem, skoro koszt rozwiązania alternatywnego bywa podobny.

Tags: ,
Author: Xion, posted under Programming »


5 comments for post “Asynchroniczność kontra wątki”.
  1. ed:
    March 11th, 2008 o 1:11

    Jeśli chodzi Ci o BackgroundWorker w .NET to jest on realizowany za pomocą innego wątku. Właściwie każda operacja asynchroniczna opiera się na utworzeniu lub wykorzystaniu istniejącego już drugiego wątku. Wątków nie unikniesz ale możesz zapakować w przyjazny interface (jak chociażby BackgroundWorker :) ).

  2. moriturius:
    March 11th, 2008 o 7:22

    Ja uważam, że z aktualnymi trendami technologicznymi najlepsze jest właśnie mnożenie wątków :) Mówię oczywiście o aspekcie wydajnościowym, bo wiadomo, że im więcej wątków tym programista musi się bardziej nagłowić.

    Powodem takiego mojego rozumowania jest to, że większość procesorów już jest dwurdzeniowych i żeby je w pełni wykorzystać to najlepiej stworzyć właśnie 2 wątki. W przyszłości może będzie jeszcze więcej rdzeni w jednym procesorze.

    No ale nie można popadać ze skrajności w skrajność. Mnożenie wątków na siłę i tam gdzie nie trzeba może dodatkowo spowolnić program lub w najlepszym wypadku nie zmienić jego wydajności – a programista i tak się namęczy.

    Programowanie to sztuka wyboru mniejszego zła :)

  3. io:
    March 11th, 2008 o 11:36

    Hej

    Tak się dzisiaj złożyło, że poruszyłeś nieco zagadnienie wielowątkowości, a akurat Jeff Atwood na swoim blogu poruszył podobny temat. Może Was, programistów gier, to nieco zainteresuje, więc pozwoliłem sobie podać adres: http://www.codinghorror.com/blog/archives/001073.html

    Trochę o grafice 3D, o renderowaniu, ray tracing i wielowątkowość.

    pozdrawiam

  4. Reg:
    March 16th, 2008 o 11:58

    Powiedziałbym wręcz, że asynchroniczne wejście-wyjście to bardziej “prawidłowa” metoda. Na przykład co, jeśli używasz wejścia-wyjścia w sposób blokujący w osobnym wątku, a użytkownik zażąda w tym czasie przerwania operacji albo zakończenia programu. KILL?

  5. Xion:
    March 16th, 2008 o 14:12

    Wątek przynajmniej można zabić, operacji asynchronicznej niekoniecznie (zależy od konkretnej sytuacji i implementacja).

Comments are disabled.
 


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