0Pricing
Ruby Academy · Lekcja

Wyjaśnienie GVL

Dlaczego wątki są ograniczone

Wyjaśnienie GVL to bezpłatna lekcja Ruby Academy na CoddyKit. To lekcja 2 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Ruby Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Ruby Academy zawiera 4 lekcji w sumie.

Czym jest GVL?

GVL (Global VM Lock, historycznie GIL) to blokada wewnątrz CRuby, standardowego interpretera Ruby.

  • Pozwala ona tylko jednemu wątkowi wykonywać kod Ruby w danej chwili.
  • Chroni wewnętrzne mechanizmy interpretera przed uszkodzeniem podczas współbieżnego dostępu.
  • Oznacza to, że kod Ruby wykonujący wyłącznie obliczenia CPU nie działa naprawdę równolegle na wielu rdzeniach.

Zrozumienie GVL wyjaśnia, kiedy wątki pomagają, a kiedy nie.

Dlaczego istnieje

Wewnętrzne mechanizmy CRuby (alokowanie obiektów, garbage collection i rozszerzenia C) nie zostały w całości zaprojektowane jako bezpieczne wątkowo. GVL zapewnia im bezpieczeństwo, wykonując kod Ruby szeregowo.

Usunięcie go w bezpieczny i uporządkowany sposób jest trudne, dlatego CRuby nadal go używa. JRuby i TruffleRuby nie mają GVL i mogą uruchamiać wątki na wielu rdzeniach.

Praca typu CPU-bound

W przypadku zadań typu CPU-bound (obliczeń matematycznych, sortowania i analizowania) wątki nie przyspieszają działania programu w CRuby. W danej chwili tylko jeden wątek wykonuje kod Ruby, więc dwa wątki CPU dają w przybliżeniu efekt jednego wątku powiększony o dodatkowy narzut.

def heavy
  sum = 0
  1_000_00.times { |i| sum += i }
  sum
end

puts heavy
puts "CPU work does not parallelize under the GVL"

Operacje I/O zwalniają GVL

Najważniejsza informacja jest taka, że blokujące operacje I/O zwalniają GVL. Gdy wątek śpi, odczytuje plik lub czeka na gniazdo, zwalnia blokadę, dzięki czemu inny wątek może wykonywać kod Ruby.

Dlatego wątki świetnie nadają się do pracy typu I/O-bound nawet w obecności GVL.

Nakładające się oczekiwanie

W tym przykładzie trzy wątki wykonują sleep. Ponieważ sleep zwalnia GVL, okresy oczekiwania nakładają się na siebie. Całkowity czas wynosi około 0.2s, a nie 0.6s.

start = Time.now

threads = (1..3).map do
  Thread.new { sleep 0.2 }
end
threads.each(&:join)

elapsed = Time.now - start
puts "Elapsed roughly: " + elapsed.round(1).to_s

Rozszerzenia C mogą go zwalniać

Dobrze napisane rozszerzenia C mogą zwalniać GVL podczas długotrwałych obliczeń natywnych za pomocą rb_thread_call_without_gvl. Dzięki temu intensywne operacje natywne mogą działać równolegle, a wątki Ruby mogą kontynuować pracę.

Niektóre biblioteki osiągają więc prawdziwą równoległość nawet w CRuby.

Wątki nadal się przełączają

Nawet w przypadku pracy CPU GVL nie zamraża pozostałych wątków na zawsze. CRuby okresowo wywłaszcza wątek, aby każdy otrzymał swoją kolej. Praca jest współbieżna (przeplatana), ale nie równoległa (wykonywana jednocześnie).

results = []
mutex = Mutex.new

threads = (1..3).map do |n|
  Thread.new do
    mutex.synchronize { results << n }
  end
end
threads.each(&:join)

puts "Collected: " + results.sort.join(", ")

Współbieżność a równoległość

Dwa ważne pojęcia:

  • Współbieżność: zadania robią postępy, przeplatając się. GVL na to pozwala.
  • Równoległość: zadania działają dokładnie w tym samym momencie na różnych rdzeniach. GVL uniemożliwia to w przypadku kodu Ruby.

Wątki zapewniają współbieżność, a Ractory zapewniają równoległość.

Omijanie GVL

Aby wykorzystać wiele rdzeni do pracy CPU w CRuby, można:

  • Uruchomić wiele procesów (każdy ma własny GVL).
  • Użyć Ractorów do uzyskania równoległości w obrębie jednego procesu.
  • Przekazać pracę do rozszerzeń C, które zwalniają GVL.

W przypadku pracy I/O zwykłe wątki zazwyczaj wystarczą.

Procesy nie współdzielą GVL

Każdy proces systemu operacyjnego uruchamia własną maszynę wirtualną Ruby z własnym GVL. Forkowanie zapewnia prawdziwą równoległość, ale procesy nie współdzielą pamięci i zużywają więcej zasobów.

puts "Main pid: " + Process.pid.to_s
puts "Each forked process has its own independent GVL"

Wybór strategii

Wskazówki dotyczące wyboru:

  • Dużo czasu spędzanego na oczekiwaniu? Proszę użyć wątków.
  • Dużo obliczeń CPU i potrzeba wykorzystania rdzeni? Proszę użyć procesów lub Ractorów.
  • Potrzebny jest współdzielony stan? Proszę użyć wątków z Mutex, pamiętając o ograniczeniach GVL.

Znajomość GVL zapobiega typowemu błędowi polegającemu na oczekiwaniu, że wątki CPU będą skalować się liniowo.

Szybki test

Sprawdź swoją wiedzę na temat GVL.

Podsumowanie: GVL

Najważniejsze informacje o Global VM Lock:

  • W CRuby tylko jeden wątek wykonuje kod Ruby w danej chwili.
  • GVL chroni wewnętrzne mechanizmy interpretera.
  • Blokujące operacje I/O zwalniają GVL, umożliwiając nakładanie się okresów oczekiwania.
  • Praca Ruby typu CPU-bound nie jest wykonywana równolegle na wielu rdzeniach.
  • Do uzyskania prawdziwej równoległości należy użyć procesów lub Ractorów.

Następnie przyjrzymy się fiberom, które zapewniają lekką współbieżność kooperatywną.

Często zadawane pytania

Czy lekcja „Wyjaśnienie GVL” jest bezpłatna?

Tak — pełny tekst „Wyjaśnienie GVL” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Ruby Academy, przejdź na CoddyKit PRO. Kurs Ruby Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „Wyjaśnienie GVL”?

Dlaczego wątki są ograniczone Ćwiczysz Ruby Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć Ruby Academy?

Nie wymagamy żadnego doświadczenia. Ruby Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 2 z 4.

Ile czasu zajmuje lekcja „Wyjaśnienie GVL”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji Ruby Academy?

Tak. Każda lekcja Ruby Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Wątki
  2. Wyjaśnienie GVL
  3. Fibers
  4. Ractors
← Powrót do Ruby Academy