Monthly archive for December, 2007

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

Jak ASP.NET naprawia HTTP

2007-12-06 12:42

Protokół HTTP i World Wide Web powstały już bardzo dawno temu, chociaż od tamtego czasu doczekały się całego mnóstwa usprawnień. Pewnie największym była możliwość generowania stron HTML dynamicznie przy użyciu skryptów CGI, PHP, i tak dalej. Dzięki temu strony umieją już całkiem sporo i nie są statycznymi dokumentami. Ich tworzenie zaczęło też bardziej przypominać pisanie normalnych aplikacji.

Pewne ograniczenia HTTP ciężko jest jednak przezwyciężyć. Największym jest chyba to, że serwery każde zgłoszenie (request), które do nich napływa, traktują zupełnie odrębnie i w oderwaniu od wszystkich innych. Działają więc na zasadzie pytanie-odpowiedź. Gdyby poszukać odpowiednika tego modelu w zwyczajnych programach, to byłyby nim narzędzia konsolowe obsługiwane w całości przełącznikami wiersza poleceń. W dobie interfejsów graficznych mieniących się wszystkimi kolorami palety RGB nie wyglądają one zbyt imponująco…
Dlatego też wszelkie platformy służące uruchamianiu aplikacji webowych starają się tę niedogodność jakoś obejść i umożliwić powiązanie poszczególnych żądań oraz przechowywanie danych pomiędzy nimi. Standardem jest mechanizm sesji, ale np. w PHP nigdy nie udało mi się do końca go zrozumieć :)

Logo ASP.NETOstatnio jednak z konieczności (nietrudno się domyślić, jakiej :)) zajmuję się ASP.NET i muszę przyznać, że tam cała sprawa została potraktowana nieporównywalnie lepiej. Przede wszystkim serwis jest tam rzeczywiście traktowany jako aplikacja, której instancja uruchamia się w momencie pierwszego requestu z danego hosta. Poszczególne strony przypominają też raczej okienka zwykłych programów, na których zamieszcza się kontrolki specyficzne dla ASP (przerabiane na wyjściu na HTML). I to ze wszystkimi konsekwencjami: one rzeczywiście istnieją na serwerze. To sprawia, że możemy np. pobrać dane formularza wypełnionego przed chwilą na poprzedniej stronie, po prostu czytając zawartość jej kontrolek.
Cała ta trwałość nie jest oczywiście aż tak daleko posunięta jak w tradycyjnych programach. Zdarza się (i to dość często), że musimy zwracać uwagę na to, kiedy strona może być przeładowywana. Ale i tak stanowi to spory postęp na przykład w stosunku do wspomnianego mechanizmu sesji (który naturalnie też jest dostępny).

Naturalnie wszystko to są jednak tylko obejścia do starego protokołu, który pierwotnie nie został zaprojektowany do tak złożonych zadań, do których się go obecnie wykorzystuje.

Tags: ,
Author: Xion, posted under Internet, Programming » 1 comment

Statystyki wejścia

2007-12-04 22:46

Koderzy wyróżniają się ponadprzeciętnym stopniem używania klawiatury, a pewnie i myszki. Miliony wciśnięć klawiszy, tysiące kliknięć i kilometry przejechane kursorem… Ale ile jest ich dokładnie? Można to policzyć jednym z wielu dostępnych programików. Samodzielnie napisanie takiej aplikacji też nie jest bardzo trudne: w Windows na przykład trzeba by użyć do tego mechanizmu hooków.

Jak każda zabawa, także i ta staje się jednak o wiele atrakcyjniejsza, jeśli w grę zaczyna wchodzić Internet :) Kiedyś funkcjonowało przedsięwzięcie znane jako Project Dolphin, którego celem było zliczanie wciśnięć klawiszy swoich użytkowników. Po rejestracji wystarczyło ściągnąć niewielki program klienta, działający w tle i wytrwale uaktualniający licznik stuknięć w klawiaturę. Co jakiś czas dane te były wysyłane na serwer.
Logo WhatPulseNa identycznej zasadzie działa serwis WhatPulse. Posiada on aczkolwiek nieco większe możliwości, jako że statystyki dotyczą też aktywności myszy, a ponadto umożliwia zakładanie osobnych profili dla różnych komputerów, na których pracujemy. Ogólna zasada jest jednak taka sama.

Co daje uczestnictwo w takim projekcie – naturalnie oprócz poświęcenia małej części zasobów systemowych? Oczywiście dozgonną satysfakcję i możliwość śledzenia rosnących numerków :) Można rzecz jasna wymyślać bardziej racjonalne wyjaśnienia, jak na przykład mierzenie wydajności programistycznej wskazywanej przez liczbę kilobajtów wklepanego tekstu. Ale ponieważ zliczane są absolutne wszystkie wciśnięcia (i zresztą nic więcej – nie jest to żaden keylogger), równie dobry wynik osiągnie i superprogramista, i nałogowy użytkownik IRC-a.

Najlepiej więc jest być naraz i jednym, i drugim :) Na pewno zaś nie zaszkodzi przyjrzeć się generowanym przez siebie statystkom. Mogą być całkiem dobrą, dodatkową motywacją do… pracy ;)

Tags: ,
Author: Xion, posted under Applications, Internet » 5 comments

Kartka papieru

2007-12-03 19:02

Teoretycznie wszystko zakodować można “na żywioł”, po prostu siadając do ulubionego środowiska programistycznego, pisząc i kompilując. Proste dzieła może i można w ten sposób stworzyć, ale do czegoś bardziej skomplikowanego zawsze pomaga chociaż pobieżny projekt.
W jakiej formie? To już nie jest sprawą taką prostą. Obecnie mamy sporo różnych narzędzi, umożliwiających formowanie naszych pomysłów w miejscu ich docelowego egzystencji – czyli programów komputerowych. I nie chodzi mi tu o aplikacje wysoce wyspecjalizowane, bo do zaprojektowania programu może się okazać przydatny edytor tekstu typu Notatnika. Każde z tych narzędzi będzie użyteczne dla określonego celu i każde ma też swoje ograniczenia.

Kilka kartek papieruAle mamy również inny sposób. Możemy odejść (albo przynajmniej się odwrócić) od komputera, wziąć kartkę, długopis i… do dzieła. Być może wkrótce posługiwanie się tak “archaicznymi” sprzętami będzie nieco staroświeckie, ale pewnie jeszcze długo będzie miało niezaprzeczalne zalety:

  • Nieograniczone możliwości formatowania :) Tekst w formie zawijasa w środku obrazka? Proszę bardzo. Diagram ze strzałkami biegnącymi między komórkami tabelki? Nie ma problemu. Treści możemy układać tak, jak chcemy i jak tylko pozwala nam na to zręczność palców – zapewne poważnie nadwerężona ich regularnym stukaniem w klawisze ;]
  • Swoboda formy. Programy komputerowe potrafią edytować tylko dokumenty w określonych formatach, jak teksty, arkusze kalkulacyjne, diagramy UML, itd. Tutaj zaś nie mamy takich ograniczeń i możemy tworzyć schematy, zestawienia, wykresy i inne pomocnicze rysunki, które nie śniły się teoretykom inżynierii oprogramowania :)
  • Dostępność. Wprawdzie teraz komputer można zabrać ze sobą niemal wszędzie, ale i tak w tej kategorii trudno o sensowne porównywanie. Papier jest jednak zdecydowanie poręczniejszy.

Każdy jednak wie rzecz jasna, jakie są jego wady. Niektóre alternatywy – jak na przykład skrobanie po tabletowym komputerze – niwelują część z nich, zbijając przy okazji niektóre zalety. Największym mankamentem jest chyba jednak to, że rysunkowe bazgroły na papierze zawsze już pozostaną bazgrołami: nie da się ich przetworzyć na użyteczną formę schematów czy tabel zrozumiałą dla komputera, a i rozpoznawanie czystego tekstu też nie jest jeszcze doskonałe.
Wygląda więc na to, że poczciwa kartka papieru jeszcze długo będzie podstawowym środkiem tworzenia przynajmniej wstępnych – nomen omen – szkiców, zostawiając bardziej szczegółowe projektowanie innym narzędziom. Warto zatem wciąż kultywować starożytną umiejętność ręcznego pisania i rysowania :)

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

Funkcje debugujące

2007-12-01 13:29

Kiedy już przekonamy się o korzyściach płynących z regularnego stosowania debuggera (a każdy początkujący programista powinien przekonać się o nich jak najszybciej), być może zaczniemy się zastanawiać, jakaż to “magia” sprawia, że cały ten proces w ogóle jest możliwy. W jaki sposób program śledzący potrafi dostać się do wnętrza naszej aplikacji i wylistować zawartość wszystkich zmiennych, nie mówiąc już o możliwości ustawiania punktów przerwań (breakpoints) czy pracy krokowej. Czy debuggery korzystają z jakichś nieudokumentowanych “wytrychów” do samego jądra systemu operacyjnego?…

Otóż niekoniecznie. Na przykład Windows API udostępnia zwyczajne funkcje systemowe, za pomocą których jeden proces może śledzić zachowanie innego. Obejmuje to przyłączenie się do innego procesu w charakterze debuggera, obsługę przeróżnych interesujących zdarzeń (jak np. załadowanie biblioteki DLL lub stworzenie nowego wątku przez proces, który śledzimy), a także odczytywanie zawartości pamięci procesu (jeśli mamy do tego uprawnienia) lub kontekstu jego wątku.
Naturalnie mało kto będzie pisał swój własny debugger, więc wspomniane funkcje są nieszczególnie przydatne dla większości programistów. Jednak istnieje też kilka takich, które można użytecznie stosować po drugiej stronie – w aplikacji, która jest debugowana:

  • OutputDebugString to prawdopodobnie ta najbardziej znana. Służy ona do wysyłania komunikatów do debuggera, które zwykle są wyświetlane w specjalnym okienku naszego IDE. Zazwyczaj jest to bardziej poręczne rozwiązanie niż chociażby pokazywanie okienek komunikatów, które trzeba przecież potwierdzać kliknięciami w OK. Funkcję tę można aczkolwiek zastąpić wypisywaniem na standardowe wyjście diagnostyczne (stderr, reprezentowane w iostream przez obiekty cerr lub wcerr).
  • DebugBreak działa z kolei jak punkt przerwania. Zasadniczo funkcja ta wywołuje odpowiedni wyjątek systemowy (nie mający za wiele wspólnego z wyjątkami języka C++), który każdy porządny debugger złapie. W środowisku programistycznym rezultatem będzie zawieszenie działania programu i ustawienie się z widokiem kodu źródłowego na miejsce wywołania funkcji, co oczywiście znakomicie ułatwia odnalezienie przyczyny błędu. Jeżeli jednak nikt nie śledzi naszej aplikacji, wówczas rzucony wyjątek spowoduje jej awaryjne zakończenie. Generalnie podobny efekt co DebugBreak powinno dać wywołanie przerwania numer 3 (czyli asm { int 3 }).
  • IsDebuggerPresent pozwala z kolei określić, czy aplikacja jest aktualnie debugowana przez jakiś inny proces. Dzięki temu możemy na przykład przekazywać do komunikatów diagnostycznych większą liczbę informacji, wiedząc, że ktoś “po drugiej stronie” faktycznie je odczytuje :)

Wprawdzie samo korzystanie z tych funkcji nie zastąpi dobrego systemu kontroli błędów i ich raportowania (np. zapisywania w dzienniku), lecz z pewnością może pomóc. Bardzo dobrze prezentuje się na przykład okienko z obszernym komunikatem o błędzie i trzema możliwościami decyzji: kontynuacji programu, przejścia do trybu debugowania albo awaryjnego zakończenia aplikacji. Przy takim rozwiązaniu aż chce się popełniać błędy ;)

Tags: , ,
Author: Xion, posted under Programming » Comments Off on Funkcje debugujące
 


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