Jak zabić wątek w C++?

Jak zabić wątek w C++?
Cóż, nie powinieneś zabijać wątku w jego wykonaniu z następujących powodów:
  • Wątek mógł otworzyć plik do pisania, a jeśli zostanie zabity, plik nie zostanie zamknięty. To jest kłopot.
  • Wątek mógł uzyskać blokadę zasobów komputerowych do jego wyłącznego użycia. Jeśli wątek zostanie zabity, zasoby pozostaną zablokowane, a inne wątki i procesy nie będą mogły korzystać z zasobów.
  • Przydzielona pamięć musi zostać zwolniona. Wątek mógł przydzielić pamięć do pewnego celu. Jeśli wątek zostanie zabity, pamięć pozostanie fałszywie przydzielona i niedostępna dla innych wątków i procesów. To jest wyciek pamięci.

Te powody i wszelkie inne oznacza, że ​​jeśli wątek zostanie zabity, zasoby, które mógłby nabyć, nie zostaną zwolnione do użytku przez inne wątki i procesy. Gdy wątek kończy się naturalnie, wszelkie pozyskane zasoby zostaną wydane.

Typowym motywem zabijania wątku jest to, że użytkownik nie potrzebuje już wyniku wątku.

Jest kilka dobrych wiadomości: C ++ 20 to najnowsza wersja C ++ dzisiaj. Klasa wątków C ++ 20 ma elementy do uwolnienia zasobów, wątku, przed jego naturalnym zakończeniem i zatrzymaniem przed naturalnym zakończeniem. W ten sposób C ++ zatrzymuje wątek i nie zabija wątku. Innymi słowy, C ++ 20 odpowiedzialnie zabija wątek. Wydawanie zasobów i zatrzymanie wątku są automatyczne. Uwaga: nie wszystkie wątki można zatrzymać w ten sposób. Takie wątki zakończyłyby się naturalnie, nawet jeśli podjęto próbę ich powstrzymania.

Biblioteka wątków zawiera następujące klasy do zatrzymania się z wydaniem zasobów: stop_token, stop_source i stop_callback. Każda z tych klas może mieć instancje obiektów. Jednak w tym samouczku rozważane są tylko Stop_Token i Stop_source.

Polecenie uruchomienia programu wątków z kompilatorem G ++ dla C+20 powinno być podobne do:

G ++ -Std = C ++ 2a Temp.cpp -lpthread -o temp

Ten samouczek wyjaśnia, jak zatrzymać wątek z wydanymi zasobami. Zatrzymanie wątku z wydanymi zasobami jest odpowiedzialnym sposobem zabicia wątku. Ten samouczek zaczyna się od podsumowania kodowania wątku.

Treść artykułu

  • Podsumowanie kodowania wątków
  • Klasa Jthread
  • Prośba o zatrzymanie wątku
  • Jest możliwe?
  • Czy złożono prośbę o zatrzymanie?
  • Wniosek

Podsumowanie kodowania wątków

Uruchomiony program w C ++ to proces. Wątek jest podprocesem procesu. Prosty program C ++ ma tylko jeden wątek, który jest funkcją Main (). Funkcja main () nie jest formalnie zadeklarowanym wątkiem. Każdy inny wątek dla tego samego programu musi zostać formalnie zadeklarowany. W programie może być więcej niż jeden wątek.

Wątek jest utworzony z klasy wątków biblioteki wątków. Pierwszym argumentem deklaracji obiektu wątku jest nazwa funkcji najwyższego poziomu. Funkcja najwyższego poziomu to efektywny wątek. Gdy obiekt jest utworzony, funkcja najwyższego poziomu zaczyna wykonywać (uruchamianie).

Jest wątek wywoławczy i nić nazywana. Niestety, jeśli wywołany wątek nie jest połączony z organu funkcyjnego wywołanego wątku, wątek wywołany może zakończyć wykonanie bez podanego wątku, które zakończyło własne wykonanie. To oznacza problem. Tak więc organ funkcyjny wywołania wątku powinien zawsze dołączyć do wywołanego wątku po instancji wywołanego wątku.

W poniższym programie obiekt wątku jest utworzony, używając funkcji najwyższego poziomu, fn ():

#włączać
#włączać
za pomocą przestrzeni nazw Std;
void fn ()
Cout <<"first code segment of thread" <Cout <<"second code segment of thread" <
int main ()

wątek thr (fn);
thr.dołączyć();
powrót 0;

Wyjście to:

Pierwszy segment kodu wątku
Drugi segment kodu wątku

Zwróć uwagę na włączenie biblioteki wątków. Zwróć uwagę, jak zakodowano pierwsze i drugie stwierdzenia głównej funkcji. Funkcja main () jest głównym wątkiem. fn () to funkcja najwyższego poziomu.

Klasa Jthread

Jthread to klasa zdefiniowana w bibliotece wątków. To jest jak klasa wątków, ale ma tę zaletę, że można go użyć do zatrzymania wątku, uwalniając zasoby. Ma funkcje członka, aby zwrócić obiekt Stop_Token i obiekt Stop_Source. Funkcje członka to:

stop_source get_stop_source ()
stop_token get_stop_token ()

Ma również funkcję członka, aby złożyć żądanie zatrzymania, czyli:

bool request_stop ()

Na razie w październiku 2021 r. Wielu kompilatorów C ++ nadal wdraża klasę JTHREAD. Jednak próbki kodu podane poniżej powinny działać, gdy kompilator wdrożył klasę JTHREAD.

Prośba o zatrzymanie wątku

Zatrzymanie wątku oznacza zatrzymanie funkcji najwyższego poziomu przed uruchomieniem. Prośba o zatrzymanie oznacza, że ​​wątek powinien zatrzymać się jak najszybciej. Jeśli żądanie nie zostanie przyznane, wątek zostanie ukończony i nie zatrzyma się przed końcem.

Jak wskazano powyżej, wątek utworzony z JTHREAD ma funkcje odpowiedzialnego zabicia wątku (zatrzymaj wątek przed zwolnieniem jego zasobów). Funkcja członka, aby żądać tego przystanku, to:

bool request_stop ()

Wartość zwracania jest prawdziwa, jeśli żądanie zostało zaakceptowane, a w przeciwnym razie fałszywe. Przyjęcie żądania nie gwarantuje, że wątek zatrzyma się jak najszybciej. Wdrożenie żądania może nie być możliwe, a wątek nie zatrzyma. Oznacza to, że powrót prawda nie oznacza, że ​​zatrzymanie jest możliwe. Poniższy program ilustruje użycie tej funkcji członka obiektu Jthread:

#włączać
#włączać
za pomocą przestrzeni nazw Std;
void fn ()
Cout <<"first code segment of thread" <Cout <<"second code segment of thread" <
int main ()

Jthread Thr (fn);
thr.request_stop ();
thr.dołączyć();
powrót 0;

Ten program jest podobny do powyższego, ale dla dwóch punktów:

  • Wątek, THR jest utworzony z klasy Jthread.
  • Oświadczenie (żądanie) w celu jak najszybszego zatrzymania wątku zostanie umieszczone przed instrukcją łączenia (). W takim przypadku wątek wywołujący jest powstrzymanie wywołanego wątku przed kontynuowaniem realizacji.

Jest możliwe?

W niektórych sytuacjach nie można zatrzymać wątku. Jednak programista nie może wiedzieć, czy wątek można zatrzymać, czy nie. W takim przypadku programista musi zapytać. Stop_source ma funkcję członka,

bool stop_possible () const

Jeśli wartość zwracana jest prawdziwa, to możliwe jest zatrzymanie wątku przed jego naturalnym zakończeniem. Jeśli wartość zwracana jest fałszywa, nie można zatrzymać wątku przed jego naturalnym zakończeniem. Jthread ma metodę, która może zwrócić obiekt Stop_Source.

Więc lepiej może być zapytanie, czy wątek można zatrzymać przed zatrzymaniem wątku. Poniższy program ilustruje to:

#włączać
#włączać
za pomocą przestrzeni nazw Std;
void fn ()
Cout <<"first code segment of thread" <Cout <<"second code segment of thread" <
int main ()

Jthread Thr (fn);
stop_source ss = thr.get_stop_source ();
if (ss.stop_possible ())
thr.request_stop ();
w przeciwnym razie
Cout <<"Thread could be stopped!" <thr.dołączyć();
powrót 0;

Segment kodu zatrzymania został umieszczony przed instrukcją połączenia.

Czy złożono prośbę o zatrzymanie?

Jeśli możliwe jest zatrzymanie wątku, nadal nie gwarantuje, że instrukcja request_stop () odniesie sukces w zatrzymaniu wątku przed jego naturalnym zakończeniem. Jeśli wątek nie zatrzymał się przed jego naturalnym zakończeniem, na co się spodziewał, programista może chcieć wiedzieć, czy wątek został poproszony o zatrzymanie instrukcji request_stop ().

Obiekt Stop_Token ma funkcję członka,

bool stop_requested ()

Ta funkcja zwraca true, jeśli złożenie żądania zatrzymania i fałszywe w przeciwnym razie. Obiekt JTHREAD może zwrócić obiekt Stop_Token z funkcją członka,

stop_token get_stop_token () const

Poniższy kod funkcji main () ilustruje, jak wiedzieć, czy wydano request_stop:

int main ()

Jthread Thr (fn);
stop_source ss = thr.get_stop_source ();
if (ss.stop_possible ())
thr.request_stop ();
w przeciwnym razie
Cout <<"Thread could be stopped!" <stop_token st = thr.get_stop_token ();
if (st.stop_requested ())
Cout <<"Still waiting for thrread to stop." <w przeciwnym razie
thr.request_stop ();
thr.dołączyć();
powrót 0;

Cały kod zatrzymania jest przed instrukcją połączenia. Nie mylaj między funkcjami request_stop () i stop_requested ().

Wniosek

Wątek może być zabijany odpowiedzialnie za pomocą C ++ 20 i wyższej. Oznacza to zatrzymanie wątku z zasobami wątku, uwolnieni. Biblioteka wątków ma klasy Stop_Token, Stop_source, Stop_Callback i Jthread za odpowiedzialne zabicie wątku. Aby użyć obiektów Stop_Token, Stop_Source i Stop_Callback, utwórz wątek z klasą Jthread. Klasa Jthread znajduje się w bibliotece wątków, która musi być zawarta w programie C ++.

Klasa Jthread ma funkcje członka, aby zwrócić obiekty Stop_Token i Stop_source. Sama klasa Jthread ma funkcję członka, request_stop (), aby zatrzymać wątek. To wniosek prawdopodobnie zostanie przyznane, ale nie ma gwarancji, że zostanie przyznane. Jeśli wniosek zostanie przyznany, wątek zatrzymuje się tak szybko, jak to możliwe, bez osiągnięcia naturalnego końca, wszystko jest równe.

Obiekt Stop_Source można użyć do zrozumienia, czy możliwe jest zatrzymanie wątku. Obiekt Stop_Token może być użyty do wiedzy, czy wydano request_stop (). Po złożeniu wniosku o zatrzymanie nie można go wycofać (kolejne żądanie zatrzymania nie ma wpływu).