Skocz do zawartości
Macok

Synchronizacja wątków

    Rekomendowane odpowiedzi

    Macok

    Myślałem, że mniejwięcej rozumiem zagadnienie synchronizacji wątków, do póki nie zobaczyłem przykładu LunarLander z dokumentacji:

    LunarView.java | Android Developers

    Nie rozumiem następujących rzeczy:

    1. Dlaczego jako mutex jest używany obiekt SurfaceHolder?

    Przecież można było w tym celu użyć dowolnego obiektu, np. Object mutex; i nie wprowadzać zbędnego zamieszania.

    2. Jaki sens ma ten zapis:

            public synchronized void restoreState(Bundle savedState) {
               synchronized (mSurfaceHolder) {
                   //TREŚĆ FUNKCJI
               }
           }

    Z tego co wiem funkcje zsynchronizowane nie mogą być wykonywane przez różne wątki w tym samym czasie, a przecież w tym miejscu i tak do tego nie dojdzie, bo cała treść funkcji jest objęta blokiem synchronized(){}.

    3. Czy taki sposób synchronizacji jest konieczny?

    W podanym przykładzie treść WSZYSTKICH funkcji wątku LunarThread jest objęta blokiem synchronizacji, co ma pewnie fatalny wpływ na wydajność.

    Z góry dziękuję za pomoc!

    Udostępnij tę odpowiedź


    Odnośnik do odpowiedzi
    Udostępnij na innych stronach
    1. Dlaczego jako mutex jest używany obiekt SurfaceHolder?

    Przecież można było w tym celu użyć dowolnego obiektu, np. Object mutex; i nie wprowadzać zbędnego zamieszania.

    Ale można było użyć obiektu mSurfaceHolder i nie tworzyć dodatkowego obiektu ;). To po pierwsze. Po drugie synchronizacja na SurfaceHolderze wskazuje, iż naszą intencją jest synchronizacja operacji na tym właśnie obiekcie. Użycie "Object mutex" było by enigmatyczne, bo nie mówiło by, co tak naprawdę ów mutex ma synchronizować.

    3. Czy taki sposób synchronizacji jest konieczny?

    W podanym przykładzie treść WSZYSTKICH funkcji wątku LunarThread jest objęta blokiem synchronizacji, co ma pewnie fatalny wpływ na wydajność.

    Hm. Osobiście uważam, że LunarLander jest o tyle fajny, iż w jednym miejscu pokazuje pewne mechanizmy przydatne w projektowaniu gry, tzn. rysowanie, obsługę wejścia, zdarzeń Activity, i tak dalej. Ale z drugiej strony, ogólny projekt gry jest raczej kiepski, nie nadający się do zastosowania w jakimkolwiek większym projekcie. Tym niemniej w takiej formie w jakiej LL został napisany użycie tych wszystkich bloków synchronizacyjnych jest potrzebne (zauważ, że wszystko sprowadza się tu do zachowania spójnego stanu gry, kiedy do Activity zawita zdarzenie, podczas gdy gra przelicza fizykę/odrysowuje grafikę). Czy ma to tak wielki wpływ na wydajność? Hm... pewnie nie aż tak wielki. Jak byś nie kombinował, synchronizacja jest niezbędna kiedy masz odpalonych kilka wątków i przy innym projekcie gry tak czy inaczej musiała by się pojawić.

    Z tego co wiem funkcje zsynchronizowane nie mogą być wykonywane przez różne wątki w tym samym czasie, a przecież w tym miejscu i tak do tego nie dojdzie, bo cała treść funkcji jest objęta blokiem synchronized(){}.

    Dobre pytanie ;). Synchroniacja na metodzie nie ma związku z SurfaceHolderem, tylko z samym wątkiem LunarThread. W tej sytuacji jedynie funkcje LunarThread.start() (kiedy utworzone zostanie Surface do rysowania) i LunarThread.restoreState() (po odpaleniu Activity) wykluczają się wzajemnie - nie wiem, na ile ma to sens... wydaje mi się, że obie metody i tak zostaną odpalone w głównym wątku aplikacji (czyli tam, gdzie konsumowane są zdarzenia ze świata zewnętrznego).

    Udostępnij tę odpowiedź


    Odnośnik do odpowiedzi
    Udostępnij na innych stronach

    podany przez ciebie przykład podwójnej synchronizacji jest w zasadzie bez sensu i nie wzoruj się na nim, nie wszystkie przykłady w poradnikach są napinane do końca z głową albo są pisane w pośpiechu, jeżeli chodzi w ogóle synchronizacje w tym przypadku chodzi o to żeby zmiany wprowadzane w środowisku były na pewno wykonane po kolejnym cyklu rysowania i obliczeń a nie podczas, tragedii by nie było gdyby pominąć synchronizacje ;)

    trzeba pamiętać o implikacji synchronizacji, każdy wątek który chce wejść w blok synchronizowany jest blokowany do momentu kiedy blok (zamek) będzie wolny, dzięki temu można wpływać na wykonywanie programu można zatrzymać wznowić itd.. wiec to nie tylko zabezpieczenie przed konkurencyjnym dostępem

    Edytowane przez zawadaki

    Udostępnij tę odpowiedź


    Odnośnik do odpowiedzi
    Udostępnij na innych stronach
    Macok

    Dzięki za wyjaśnienie :)

    Jeszcze jedno pytanie - jak już pisał c2h5oc2h5 ogólny projekt gry jest w LunarLanderze raczej kiepski.

    Rozumiem, że w większym projekcie powinno się zrobić kolejkowanie zdarzeń tak?

    Wydaje mi się też, że gdyby zrobić kolejkę zdarzeń to pozbylibyśmy się większości bloków synchronized, bo wątek UI nie operowałby na danych wątku gry bezpośrednio, tylko za pomocą kolejki zdarzeń.

    Mam rację?

    Udostępnij tę odpowiedź


    Odnośnik do odpowiedzi
    Udostępnij na innych stronach

    Prawda. Wystarczy wtedy synchronizować dostęp do kolejki, od razu zrobi się przejrzyściej :). Swoją drogą jest to zabieg zwiększający jedynie przejrzystość, na wydajność raczej nie będzie miał większego wpływu. Tym niemniej pisanie kodu łatwego w utrzymaniu to dobra praktyka :).

    Btw - możesz sobie poprzeglądać źródła otwartych projektów (z Twoich postów wnioskuję, że interesują Cię gry), można w nich czasem znaleźć inspirację. Polecam Replica Island, zwłaszcza część z komponentami. Możesz też zerknąć na kod projektu, który narodził się na naszym forum - RacerTC. Rzecz wprawdzie jeszcze ma daleką drogę do przebycia zanim będzie się mogła tytułować grą z prawdziwego zdarzenia, ale "rdzeń" silnika jest sprawny - w środku znajdziesz m.in. wspomnianą kolejkę komend.

    Jeszcze jedna sprawa - w ramach uproszczenia obsługi np. grafiki (w szczególności niskopoziomowego rysowania w OpenGL'u - okazuje się, że na dłuższą metę Canvas to kiepskie rozwiązanie dla wszystkiego, co jest trochę bardziej skomplikowane niż LunarLander :)) możesz zainteresować się biblioteką libgdx, albowiem wygląda bardzo zacnie i pomocnie.

    Udostępnij tę odpowiedź


    Odnośnik do odpowiedzi
    Udostępnij na innych stronach

    Jeśli chcesz dodać odpowiedź, zaloguj się lub zarejestruj nowe konto

    Jedynie zarejestrowani użytkownicy mogą komentować zawartość tej strony.

    Zarejestruj nowe konto

    Załóż nowe konto. To bardzo proste!

    Zarejestruj się

    Zaloguj się

    Posiadasz już konto? Zaloguj się poniżej.

    Zaloguj się

    • Ostatnio przeglądający   0 użytkowników

      Brak zarejestrowanych użytkowników przeglądających tę stronę.

    x