Wątki pojawiają się w dwóch perspektywach: systemy operacyjne i języki programowania. W obu przypadkach istnieje pewna zmienność atrybutów wątku.
Minimalna definicja wątku polega na tym, że to, co dzieje się w sekwencji, jedna po drugiej.
W typowym modelu wykonania maszyny każdy wątek ma własny zestaw rejestrów ogólnego przeznaczenia i własny licznik programów. Jeśli urządzenie określa konkretny rejestr jako wskaźnik stosu, dla każdego wątku jest jedna kopia.
Z punktu widzenia systemu operacyjnego, minimum systemu operacyjnego do obsługi wątków zapewnia sposób przełączania się między nimi. Może się to zdarzyć albo automatycznie ( wyprzedzająca wielozadaniowość, albo tylko wtedy, gdy wątek jednoznacznie zażąda (wielozadaniowość kooperacyjna; w takim przypadku nici są czasami nazywane włóknami ). Istnieją również modele hybrydowe o wydajności wyprzedzającej i kooperacyjnej, np. Wyprzedzanie między wątkami różnych grup lub zadania, ale wyraźne wyniki między wątkami tej samej grupy / zadania. Przełączanie między wątkami wymaga co najmniej zapisania wartości rejestru starego wątku i przywrócenia wartości rejestru nowego wątku.
W wielozadaniowym systemie operacyjnym zapewniającym izolację między zadaniami (lub procesami można traktować te terminy jako synonimy w kontekście systemu operacyjnego), każde zadanie ma swoje własne zasoby, w szczególności przestrzeń adresową, ale także otwarte pliki, uprawnienia itp. Izolacja ma do dostarczenia przez jądro systemu operacyjnego , jednostkę ponad procesami. Każde zadanie zwykle ma co najmniej jeden wątek - zadanie, które nie wykonuje kodu, nie jest zbyt użyteczne. System operacyjny może, ale nie musi obsługiwać wielu wątków w tym samym zadaniu; na przykład oryginalny uniks nie. Zadanie może nadal uruchamiać wiele wątków, organizując przełączanie między nimi - nie wymaga to żadnych specjalnych uprawnień. Nazywa się to „ wątkami użytkownika”, Szczególnie w kontekście Uniksa. Obecnie większość systemów uniksowych zapewnia wątki jądra, w szczególności dlatego, że jest to jedyny sposób na uruchomienie wielu wątków tego samego procesu na różnych procesorach.
Większość zasobów systemu operacyjnego oprócz czasu obliczeń jest dołączona do zadań, a nie wątków. Niektóre systemy operacyjne (na przykład Linux) wyraźnie ograniczają stosy, w którym to przypadku każdy wątek ma swój własny; ale istnieją systemy operacyjne, w których jądro nie wie nic o stosach, są one tylko częścią stosu. Jądro zazwyczaj również zarządza kontekstem jądra dla każdego wątku, który jest strukturą danych zawierającą informacje o tym, co wątek obecnie robi; pozwala to jądrze obsługiwać wiele wątków zablokowanych w wywołaniu systemowym w tym samym czasie.
Jeśli chodzi o system operacyjny, wątki zadania wykonują ten sam kod, ale znajdują się w różnych pozycjach w tym kodzie (różne wartości liczników programu). Może się zdarzyć lub nie, że pewne części kodu programu są zawsze wykonywane w określonych wątkach, ale zwykle istnieje wspólny kod (np. Funkcje narzędziowe), który można wywołać z dowolnego wątku. Wszystkie wątki widzą te same dane, w przeciwnym razie byłyby uważane za różne zadania; jeśli do niektórych danych można uzyskać dostęp tylko za pomocą określonego wątku, zwykle dotyczy to wyłącznie języka programowania, a nie systemu operacyjnego.
W większości języków programowania pamięć jest dzielona między wątkami tego samego programu. Jest to model współdzielonego programowania pamięci ; jest bardzo popularny, ale także bardzo podatny na błędy, ponieważ programista musi uważać, gdy dostęp do tych samych danych jest możliwy przez wiele wątków, ponieważ mogą wystąpić warunki wyścigu . Zauważ, że nawet zmienne lokalne mogą być współużytkowane między wątkami: „zmienna lokalna” (zwykle) oznacza zmienną, której nazwa jest poprawna tylko podczas jednego wykonania funkcji, ale inny wątek może uzyskać wskaźnik do tej zmiennej i uzyskać do niej dostęp.
Istnieją również języki programowania, w których każdy wątek ma swoją pamięć, a komunikacja między nimi odbywa się poprzez wysyłanie wiadomości kanałami komunikacyjnymi. Jest to model przekazywania współbieżnego programowania. Erlangjest głównym językiem programowania, który koncentruje się na przekazywaniu wiadomości; jego środowisko wykonawcze ma bardzo lekką obsługę wątków i zachęca programy napisane z wieloma krótkotrwałymi wątkami, w przeciwieństwie do większości innych języków programowania, w których tworzenie wątku jest stosunkowo kosztowną operacją, a środowisko wykonawcze nie może obsługiwać bardzo dużych liczba wątków jednocześnie. Sekwencyjny podzbiór Erlanga (część języka, która zachodzi w wątku, w szczególności manipulacja danymi) jest (głównie) czysto funkcjonalny; w ten sposób wątek może wysłać wiadomość do innego wątku zawierającego pewne dane i żaden wątek nie musi się martwić, że dane zostaną zmodyfikowane przez inny wątek podczas jego używania.
Niektóre języki łączą oba modele, oferując lokalną pamięć wątkową, z systemem typów lub bez niego, aby odróżnić lokalną pamięć wątkową od globalnych. Lokalne przechowywanie wątków jest zwykle wygodną funkcją, która pozwala zmiennej nazwie wyznaczyć różne miejsca przechowywania w różnych wątkach.
Niektóre (trudne) działania następcze, które mogą być interesujące dla zrozumienia, jakie są wątki:
- Jakie minimum musi zrobić jądro, aby obsługiwać wiele wątków?
- Co trzeba zrobić w środowisku wieloprocesorowym, aby przeprowadzić migrację wątku z jednego procesora do drugiego?
- Co trzeba zrobić, aby wdrożyć wielowątkowość kooperacyjną ( coroutines ) w swoim ulubionym języku programowania bez wsparcia ze strony systemu operacyjnego i bez korzystania z jego wbudowanej obsługi, jeśli taka istnieje? (Uważaj, że w większości języków programowania brakuje niezbędnych prymitywów do implementacji coroutines w jednym wątku.)
- Jak mógłby wyglądać język programowania, gdyby miał współbieżność, ale nie miał (jawnej) koncepcji wątków? (Pierwszy przykład: rachunek pi ).
To zależy. Jeśli weźmiesz pod uwagę wątki zdefiniowane np. Przez POSIX (i oferowane przez systemy Unix) lub Windows (nie znając później, będziesz musiał zapytać konkretnie), to daje odpowiedź (zasadniczo jak wyjaśnia odpowiedź @WanderingLogic). Linux ma swój własny pomysł na wątki, wykorzystujący niestandardowe
clone(2)
wywołanie systemowe. Zapewnia to drobiazgową kontrolę nad tym, co rodzice i dzieci dzielą. Chodzi o to, aby miećfork(2)
ivfork(2)
zasadniczo owijać wokół wewnętrznegoclone(2)
, nazywając go specyficznymi flagami, tj. Możesz tworzyć „wątki”, które dzielą się niczym z rodzicem. Szczegółowe informacje można znaleźć na stronie podręcznika, są one dostępne on-line np . Tutaj . Tak, Linux oferuje wątki w stylu POSIX, ale znacznie więcej.źródło
Udostępnianie wątków:
Wątki mają swoje własne:
źródło