why javascript is single threaded
Dlaczego JavaScript jest jednowątkowy
JavaScript słynie z tego, że jest „single-threaded” (jednowątkowy) — to decyzja projektowa, która przez dekady kształtowała rozwój aplikacji webowych. Jeśli zastanawiasz się, dlaczego JavaScript nie uruchamia wielu wątków jak inne języki — a mimo to radzi sobie z pobieraniem danych, timerami i interakcjami użytkownika bez zawieszania strony — ten przewodnik wyjaśnia, co naprawdę oznacza „single-threaded”, dlaczego język zaprojektowano w ten sposób i jak współczesny JavaScript osiąga współbieżność dzięki modelowi zdarzeniowemu.
Co oznacza „single-threaded” w JavaScript
Gdy mówimy, że JavaScript jest jednowątkowy, zwykle chodzi o to, że w przeglądarce (i wielu innych runtime’ach) kod JavaScript wykonuje się na jednym głównym wątku. To znaczy, że w danym momencie wykonywany jest tylko jeden fragment kodu JavaScript.
To jednak nie znaczy, że JavaScript „nie potrafi robić kilku rzeczy naraz”. Zamiast tego zaprojektowano go tak, by unikać blokowania głównego wątku. Prace w tle (np. operacje sieciowe czy timery) obsługuje środowisko uruchomieniowe, a JavaScript wraca do działania, gdy wyniki są gotowe.
Kluczowa myśl:
- Jeden wątek JavaScript wykonuje Twój kod.
- Inne części systemu (przeglądarka/runtime) obsługują I/O i timery.
- Gdy te zadania się kończą, JavaScript dostaje asynchroniczne wywołanie zwrotne (callback).
Dlaczego JavaScript stał się jednowątkowy
1) Wczesne przeglądarki potrzebowały prostoty i niezawodności
JavaScript pojawił się w połowie lat 90., gdy zachowanie przeglądarek na różnych urządzeniach i platformach było niespójne. Model jednego wątku był prostszą drogą do zapewnienia przewidywalności.
Gdyby wiele wątków mogło jednocześnie czytać i zapisywać współdzielone dane, język musiałby mieć złożone reguły dotyczące:
- race conditions (warunków wyścigu),
- widoczności pamięci,
- blokad i synchronizacji,
- deterministycznej semantyki współbieżności.
Dla wczesnej technologii webowej, kierowanej do milionów deweloperów i użytkowników, prostota miała kluczowe znaczenie. Jednowątkowość pozwoliła dostarczyć spójne rezultaty bez zmuszania każdego programisty do opanowania zawiłości współbieżności.
2) Krytyczne było unikanie „zamarzania” UI
W przeglądarce JavaScript często kontroluje interfejs użytkownika: reaguje na kliknięcia, modyfikuje DOM, animuje elementy i przetwarza dane wejściowe.
Gdyby wiele wątków mogło równocześnie modyfikować DOM, łatwo byłoby o:
- uszkodzony lub niespójny stan UI,
- nieprzewidywalne błędy renderowania,
- niespójną obsługę zdarzeń.
Utrzymując główny kontekst wykonania JavaScript jako jednowątkowy, przeglądarki zapewniają kontrolowaną kolejność operacji na DOM. To zmniejsza ryzyko „tajemniczych” błędów i stabilizuje aktualizacje UI.
3) JavaScript zaprojektowano wokół pętli zdarzeń (event loop)
JavaScript jest nie tylko jednowątkowy — jest sterowany zdarzeniami. Runtime używa pętli zdarzeń do zarządzania operacjami asynchronicznymi.
Zamiast „pauzować i czekać” (co blokowałoby wątek), JavaScript planuje pracę na później i kontynuuje wykonywanie innych zadań. Gdy operacja się kończy, runtime umieszcza callback (lub rozwiązuje Promise) w kolejce zdarzeń.
Taki projekt daje płynne doświadczenie dla deweloperów:
- żądania sieciowe nie zamrażają UI,
- zdarzenia użytkownika są obsługiwane szybko,
- długie operacje można dzielić na mniejsze porcje.
Dlatego JavaScript może sprawiać wrażenie wysoce „współbieżnego”, mimo jednego wątku.
Runtime przeglądarki: gdzie naprawdę dzieje się „asynchroniczność”
Zrozumienie jednowątkowości wymaga wiedzy, co „async” znaczy na poziomie runtime’u.
Gdy uruchamiasz kod:
```js
fetch("/data")
.then(res => res.json())
.then(data => console.log(data));
```
Przebieg w prostych słowach:
1. JavaScript zaczyna wykonywanie na głównym wątku.
2. `fetch()` uruchamia żądanie sieciowe obsługiwane poza wątkiem JavaScript.
3. JavaScript kończy bieżące wykonanie i oddaje sterowanie pętli zdarzeń.
4. Gdy odpowiedź sieciowa nadejdzie, przeglądarka/runtime umieszcza handlery `.then()` w kolejce.
5. Pętla zdarzeń podejmuje je później i JavaScript wznawia pracę.
Twój kod pozostaje jednowątkowy, ale system wciąż wykonuje operacje I/O współbieżnie.
A co z Web Workers i wielowątkowością?
„Jednowątkowy” nie znaczy, że JavaScript nigdy nie może używać wielu wątków. W przeglądarce możesz użyć Web Workers do uruchamiania JavaScript w wątkach w tle.
Każdy Web Worker ma własny kontekst wykonania i własną pętlę zdarzeń. To oznacza:
- worker uruchamia JavaScript na oddzielnym wątku,
- komunikacja z głównym wątkiem odbywa się przez przesyłanie komunikatów (message passing).
Współczesny JavaScript może więc być „wielowątkowy” poprzez wiele kontekstów — ale domyślnie unika wspólnej pamięci, co zapobiega wielu błędom współbieżności.
Kompromis: bezpieczeństwo kontra złożoność
Jednowątkowość to świadomy kompromis:
Korzyści
- Mniej race conditions w większości kodu aplikacyjnego.
- Deterministyczna kolejność kodu synchronicznego.
- Stabilne operacje na DOM, bo aktualizacje zachodzą sekwencyjnie.
- Niższe obciążenie poznawcze: nie trzeba na co dzień myśleć o blokadach i wątkach.
Koszty
- Jeśli JavaScript wykona długie, CPU‑chłonne zadanie (np. ciężkie pętle, parsowanie dużego JSON-a, złożone przetwarzanie danych), zablokuje główny wątek.
- „Współbieżność” osiąga się przez async I/O i planowanie zadań — nie przez równoległe wykorzystanie CPU.
Dlatego kosztowne obliczenia często przenosi się do:
- Web Workers,
- przetwarzania po stronie serwera,
- zoptymalizowanych algorytmów,
- grupowania i dzielenia pracy na mniejsze porcje.
Dlaczego Promises i async/await nie łamią jednowątkowości
Widzisz „async/await” i możesz założyć, że JavaScript uruchamia kod w równoległych wątkach. Ale `async/await` głównie zmienia sposób PISANIA asynchronicznych przepływów, a nie liczbę wątków.
- `await` wstrzymuje bieżącą funkcję asynchroniczną bez blokowania pętli zdarzeń.
- Reszta programu działa dalej.
- Gdy oczekiwana operacja się zakończy, funkcja kontynuuje w tym samym, jednowątkowym kontekście.
Język pozostaje jednowątkowy, a mimo to wspiera wykonanie asynchroniczne.
Model współbieżności JavaScript: mikrozadania, makrozadania i pętla zdarzeń
„Jednowątkowość” w JavaScript jest ściśle związana z pętlą zdarzeń i kolejkami zadań:
- Makrozadania (macrotasks): zdarzenia takie jak timery (`setTimeout`), callbacki I/O oraz niektóre zdarzenia UI.
- Mikrozadania (microtasks): callbacki Promise (`then`, `catch`, `finally`).
Te kolejki wpływają na kolejność wykonania. Deweloperzy często zauważają, że handlery Promise uruchamiają się „przed” callbackami `setTimeout` — to bezpośredni efekt strategii planowania pętli zdarzeń.
Wniosek: JavaScript jest jednowątkowy, ale ma precyzyjną kontrolę nad tym, kiedy uruchamia pracę.
Sedno: dlaczego JavaScript jest jednowątkowy
JavaScript jest jednowątkowy, bo zaprojektowano go z myślą o:
- niezawodności w przeglądarce,
- uproszczonej semantyce współbieżności,
- bezpiecznym, przewidywalnym dostępie do DOM,
- architekturze pętli zdarzeń, która zapewnia nieblokujące I/O.
Ten model pomaga JavaScriptowi być szybkim w pracy z UI, korzystając z runtime’u do asynchronicznej obsługi zadań zewnętrznych.
Podsumowanie
Jednowątkowa konstrukcja JavaScript to nie ograniczenie, lecz fundament. Stawia na przewidywalne wykonanie i bezpieczne interakcje z UI, a współbieżność zapewnia przez pętlę zdarzeń, Promises i asynchroniczne operacje zarządzane przez runtime. Gdy naprawdę potrzebujesz równoległej pracy CPU, JavaScript oferuje alternatywy w postaci Web Workers — ale domyślny model utrzymuje stabilność platformy webowej i przyjazność dla deweloperów.
W praktyce: unikaj blokowania głównego wątku, opieraj I/O na wzorcach asynchronicznych i używaj workerów do ciężkich obliczeń.
Jeśli chcesz, mogę dodać też sekcję „Częste nieporozumienia: jednowątkowość vs równoległość” oraz „Kiedy jednowątkowość szkodzi wydajności (i jak to naprawić)” do Twojego hasła w glosariuszu.
Gotowy, aby scentralizować swoje know-how z pomocą AI?
Rozpocznij nowy rozdział w zarządzaniu wiedzą — gdzie Asystent AI staje się centralnym filarem Twojego cyfrowego wsparcia.
Umów bezpłatną konsultacjęPracuj z zespołem, któremu ufają firmy z czołówki rynku.




