Problemy które tutaj omówię są dosyć ogólne i dotyczą konstruowania aplikacji serverowej z użyciem wielowątkowości. Nie wiem czy problemy te wynikają z mojej niewiedzy, złego podejścia do zagadnienia czy słabych punktów języka, w każdym razie:
Próbuję napisać server gry. Korzystam z "nonblocking I/O" w oparciu o artykuł: http://www-128.ibm.com/developerworks/java/library/j-javaio/ Nie wnikając w szczegóły opisanej w tym artykule techniki, powiem tylko że nie do końca jest ona "nonblocking". Prgoram wykorzystujący tą technikę blokuje się gdy zaczyna nasłuchiwać nowego połączenia tak więc w moim serverze obsługą nawiązanych już połączeń mogę się zając w "głównym wątku" ale na potrzebę nasłuchu nowych połączeń muszę utworzyć oddzielny wątek. Zgodnie z moją koncepcją server składałby się z trzech wątków:
1.Wątek nasłuchu nowych połączeń: nasłuchujue nowego połączenia, akceptuje je i przekazuje nawiązane połączenie do wątku głównego.
2.Wątek główny: Odbiera informacje od klientów, przetwarza je i odsyłą z powrotem.
3.Wątek połączenia z bazą danych: Server ma się łączyć i utrzymywać komunikację z bazą SQL która będzie się znajdować na innej maszynie. na razie nie zagłębiałem się w to zagadnienie ale podejrzewam że jest tam masa operacji blokujących więc przydzielam temu zagadnieniu oddzielny wątek.
Z takiego podziału wynika że różne wątki muszą operować na tych samych danych np: wątek 1 po nawiązaniu nowego połączenia musi dodać nowego klienta do jakiejś umownej listyKlientów, natomiast wątek 2 tą samą listę będzie czytał w celu przetwarzania danych. Ponieważ taka czynność może grozić zepsuciem danych, z pomocą przychodzi nam synchornizacja. W przykładach w oparciu o które omówiony jest rozdział "Wielowątkowość" w książce "JAVA 2 - Techniki Zaawansowane" synchronizowana jest jedna metoda operująca na jakiś tam danych. Metoda ta jest wywoływana w wielu wątkach i dlatego deklarowana jest ze słowem kluczowym synchronized albo tworzona w niej jest jawna blokada. No i problem z głowy. Jednak cała ta idea synchronizacji zdaje się nie mieć zastosowania w moim przypadku. Wątek 1 wywoływać będzie przykładową metodą DodajKlientaDoListy(Klient klient) a wątek 2 wywoływać będzie zupełnie inną metodę (np: DaneOKliencie PrzeczytajDaneOKliencie(Klient klient) ) która operować będzie na tych samych danych, tak więc to że użyję przy deklaracji obydwu metod słowa kluczowego synchronized nie uchroni mnie w żaden sposób przed popsuciem danych. No i cała koncepcja synchronizacji pada.
Pierwsze moje pytanie to: Czy wyciągnięty powyżej wniosek jest prawidłowy?
Jesli tak to drugie pytanie brzmi: Jak sobie poradzić z tym problemem?
No i jeszcze jedno zagadnienie:
Załóżmy że mój server składa się tylko z watków numer 1 i 2. Wątek numer 1 ma to do siebie że musi wywołać metodę blokującą żeby zaakceptować połączenie i dzieje się tak nawet gdy żadne połączenie nie oczekuje na zaakceptowanie bo nie da się sprawdzić czy jakieś połączenie czeka na zaakceptowanie bez wywołania tej samej metody blokującej. W praktyce oznacza to że wątek ten będzie się po zaakceptowaniu każdego nowego połaczenia zawieszał aż do momentu nadejścia nowego połączenia. I o ile mi wiadomo wątek taki będzie działał dopuki nie wywłaszczy go system operacyjny stwierdzając że działa on już za długo. Natomiast wątek numer 2 będzie zawierał zdecydowaną większość kodu servera i będzie zdecydowanie bardziej czasochłonny. Tak więc chcąc mu dać możliwie dużo czasu na działanie nie będe go zawieszał po każdej pętli tylko pozwole mu działać aż wywłaszczy go system. Zakładam że system wywłaszczać będzie każdy z wątków po takim samym czasie czyli procesor będzie poświęcał tyle samo czasu wątkowi numer 1 jaki i wątkowi numer 2. Ale biorąc pod uwagę że 95% kodu znajduje się w wątku numer 2 to w praktyce oznaczać to będzie że przez połowę czasu pracy servera procesor pracuje na pełnych obrotach a przez połowę czasu nie robi nic czekając aż zakończy swoje działanie jedna metoda blokujaca, innymi słowy mój server będzie miał w praktyce dostęp tylko do połowy mocy obliczeniowej komputera. Czy tak rzeczywiście będzie? Czy można jakoś zmusić wątek nr 1 do szybszego wywłaszczenia? Czy można w jakiś sposób stwierdzić że wątek numer 1 wykonuje obecnie metodę blokującą i zmienić status wątku? A może problem ten wynika z mojego błędnego podejścia do zagadnienia?