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 ).