Widziałem ten link: Implementowanie wzajemnego wykluczania w JavaScript . Z drugiej strony przeczytałem, że w javascript nie ma wątków, ale co to dokładnie oznacza?
Kiedy występują zdarzenia, gdzie w kodzie mogą one przerwać?
A jeśli w JS nie ma wątków, czy muszę używać muteksów w JS, czy nie?
Konkretnie zastanawiam się o skutkach korzystania z funkcji zwanych przez setTimeout()
a XmlHttpRequest
„s onreadystatechange
od zmiennych dostępnych globalnie.
javascript
multithreading
mutex
Ovesh
źródło
źródło
Odpowiedzi:
Javascript jest zdefiniowany jako język ponownie wprowadzany , co oznacza, że użytkownik nie ma żadnych wątków, a implementacja może zawierać wątki. Funkcje takie jak
setTimeout()
i asynchroniczne wywołania zwrotne muszą czekać na uśpienie silnika skryptów, zanim będą mogły zostać uruchomione.Oznacza to, że wszystko, co dzieje się w wydarzeniu, musi zostać zakończone, zanim następne zdarzenie zostanie przetworzone.
Biorąc to pod uwagę, możesz potrzebować muteksu, jeśli kod robi coś, w którym oczekuje, że wartość nie zmieni się między momentem uruchomienia zdarzenia asynchronicznego a wywołaniem wywołania zwrotnego.
Na przykład, jeśli masz strukturę danych, w której klikasz jeden przycisk i wysyła ona XmlHttpRequest, która wywołuje wywołanie zwrotne, zmienia strukturę danych w destrukcyjny sposób, i masz inny przycisk, który zmienia tę samą strukturę danych bezpośrednio, między momentem, w którym zdarzenie zostało uruchomione, a gdy wywołanie zwrotne zostało wykonane, użytkownik mógł kliknąć i zaktualizować strukturę danych przed wywołaniem zwrotnym, co może spowodować utratę wartości.
Chociaż możesz stworzyć taki stan wyścigu, bardzo łatwo jest temu zapobiec w swoim kodzie, ponieważ każda funkcja będzie atomowa. Wymagałoby to dużo pracy i wymagałoby kilku dziwnych wzorców kodowania, aby w rzeczywistości stworzyć warunki wyścigu.
źródło
Odpowiedzi na to pytanie są nieco nieaktualne, choć poprawne w momencie ich udzielenia. I nadal poprawne, jeśli patrzysz na aplikację javascript po stronie klienta, która NIE korzysta z webworkerów.
Artykuły o pracownikach internetowych:
wielowątkowość w javascript przy użyciu webworkers
Mozilla na webworkersach
To wyraźnie pokazuje, że javascript za pośrednictwem pracowników sieci ma możliwości wielowątkowości. Jeśli chodzi o pytanie, czy muteksy są potrzebne w javascript? Nie jestem tego pewien. Ale ten post dotyczący przepływu stosów wydaje się mieć znaczenie:
Wzajemne wykluczanie N wątków asynchronicznych
źródło
Jak wskazuje @william,
Można to uogólnić dalej - jeśli twój kod robi coś, w którym oczekuje wyłącznej kontroli nad zasobem do czasu rozwiązania asynchronicznego żądania, możesz potrzebować muteksu.
Prostym przykładem jest przycisk, który odpala wywołanie Ajax w celu utworzenia rekordu w zapleczu. Możesz potrzebować trochę kodu, aby uchronić Cię przed wywołaniem kliknięcia przez zadowolonych użytkowników, a tym samym utworzenia wielu rekordów. istnieje kilka podejść do tego problemu (np. wyłącz przycisk, włącz przy sukcesie Ajax). Możesz także użyć prostego zamka:
Nie jestem pewien, czy to najlepsze podejście i chciałbym zobaczyć, jak inni radzą sobie z wzajemnym wykluczaniem w javascript, ale o ile wiem, jest to prosty muteks i jest przydatny.
źródło
while
withsetTimeout
lub asetInterval
withclearInterval
after n nieudanych, aby mieć logikę ponawiania i limitu czasu. Pozostawienie tak, jak jest, oznacza, że po prostu ominiesz kod, który jest zablokowany. Zewnętrzna obsługa muteksów i obiektów współdzielonych jest równie ważna, jak same implementacje.JavaScript jest jednowątkowy ... chociaż Chrome może być nową bestią (myślę, że jest również jednowątkowy, ale każda karta ma swój własny wątek JavaScript ... Nie zaglądałem do tego szczegółowo, więc nie cytuj mnie tam).
Jednak jedną rzeczą, o którą musisz się martwić, jest to, w jaki sposób Twój JavaScript obsłuży wiele żądań Ajax wracających w innej kolejności, w jakiej je wysyłasz. Tak więc, wszystko, o co naprawdę musisz się martwić, to upewnić się, że twoje wywołania Ajax są obsługiwane w taki sposób, że nie nadepną sobie nawzajem na nogi, jeśli wyniki pojawią się w innej kolejności niż je wysłałeś.
Dotyczy to również limitów czasu ...
Kiedy JavaScript staje się wielowątkowy, może martwić się o muteksy i tym podobne ...
źródło
Tak, muteksy mogą być wymagane w JavaScript podczas uzyskiwania dostępu do zasobów współdzielonych między kartami / oknami, takich jak localStorage .
Na przykład, jeśli użytkownik ma otwarte dwie karty, prosty kod, taki jak poniższy, jest niebezpieczny:
Od czasu, gdy element localStorage jest „got” i „set”, inna karta mogłaby zmodyfikować wartość. Generalnie jest to mało prawdopodobne, ale możliwe - musiałbyś samodzielnie ocenić prawdopodobieństwo i ryzyko związane z jakimkolwiek sporem w określonych okolicznościach.
Więcej informacji znajdziesz w następujących artykułach:
źródło
JavaScript, język , może być tak wielowątkowy, jak chcesz, ale osadzanie przeglądarki silnika javascript uruchamia tylko jedno wywołanie zwrotne (onload, onfocus, <script> itp.) Na raz (przypuszczalnie na kartę). Sugestia Williama dotycząca używania Mutexa do zmian między rejestracją a otrzymaniem oddzwonienia nie powinna być traktowana zbyt dosłownie z tego powodu, ponieważ nie chciałbyś blokować w interweniującym wywołaniu zwrotnym, ponieważ wywołanie zwrotne, które je odblokuje, zostanie zablokowane za bieżącym wywołaniem zwrotnym ! (Wow, angielski jest do niczego, jeśli chodzi o rozmawianie o wątkach.) W tym przypadku prawdopodobnie chcesz zrobić coś na wzór ponownego wysłania bieżącego zdarzenia, jeśli flaga jest ustawiona, dosłownie lub za pomocą funkcji setTimeout ().
Jeśli używasz innego osadzania JS i wykonuje on wiele wątków jednocześnie, może to być nieco bardziej ryzykowne, ale ze względu na sposób, w jaki JS może tak łatwo używać wywołań zwrotnych i blokować obiekty w dostępie do właściwości, jawne blokowanie nie jest tak potrzebne . Byłbym jednak zaskoczony, gdyby osadzanie zaprojektowane dla ogólnego kodu (np. Skryptów gier), które wykorzystywało wielowątkowość, nie dawało również wyraźnych prymitywów blokujących.
Przepraszam za ścianę tekstu!
źródło
Zdarzenia są sygnalizowane, ale wykonanie JavaScript jest nadal jednowątkowe.
Rozumiem, że po zasygnalizowaniu zdarzenia silnik zatrzymuje to, co obecnie wykonuje, aby uruchomić procedurę obsługi zdarzenia. Po zakończeniu obsługi, wykonywanie skryptu jest wznawiane. Jeśli program obsługi zdarzeń zmienił niektóre współdzielone zmienne, wznowiony kod spowoduje, że te zmiany pojawią się „nieoczekiwanie”.
Jeśli chcesz "chronić" współdzielone dane, wystarczy prosta flaga boolowska.
źródło