Jak odłączyć wątek w C++?

Jak odłączyć wątek w C++?
Wątek odłącza się od czego? - Nić odłącza się od połączenia. Następne pytanie brzmi: „Co to jest dołączenie?” - Zamiast mieć program stwierdzeń od początku do końca, sekwencyjnie, program można pogrupować w specjalne sekcje stwierdzeń. Specjalne sekcje nazywane są wątkami, które mogą następnie działać równolegle lub jednocześnie. Aby przekonwertować zestaw instrukcji na wątek, potrzebne jest specjalne kodowanie. Niestety wątki w C ++ działałyby niezależnie, jeśli nie zostaną połączone. W takiej sytuacji drugi wątek może zakończyć się po zakończeniu głównego wątku. To zwykle nie jest pożądane.

Aby było każde połączenie, potrzebne są dwa wątki. Jeden wątek wywołuje drugi wątek. Dołączenie do wątku oznacza, że ​​podczas gdy wątek wywołujący jest zatrzymany na pozycji i czekał na wywołanie wątku ukończenia wykonania (do końca), zanim będzie kontynuować własną realizację. W pozycji, w której wstrzymuje się wątek, istnieje wyrażenie połączenia. Takie zatrzymanie nazywa się blokowaniem.

Jeśli nazywany wątek trwa zbyt długo, aby zakończyć i prawdopodobnie zrobił to, czego oczekiwał wątek wywoławczy, to wątek wywołania może go odłączyć. Po odłączeniu, jeśli wywołany wątek zakończy się po wątku wywoławczym, nie powinno być problemu. Odłączanie oznacza złamanie połączenia (link).

Przypomnienie sobie czegoś

Wątek to funkcja najwyższego poziomu, która została zamknięta w obiekcie wątku, utworzona z klasy wątku. Ponowanie wątku z funkcją najwyższego poziomu oznacza wywołanie funkcji. Oto prosty program wątków z instrukcją łączenia:

#włączać
#włączać
za pomocą przestrzeni nazw Std;
void func ()
Cout <<"… from thread!" <<'\n';

int main ()

wątek thd (func);
thd.dołączyć();
/* sprawozdania */
powrót 0;

Są tutaj dwa wątki: funkcja obiektu, thd i main (). Główna funkcja jest jak główny wątek. Zwróć uwagę na włączenie biblioteki wątków. Wyjście to:

… Z wątku!

W wierszu polecenia program C ++ 20 z wątkami powinien być dowodzony w następujący sposób dla kompilatora G ++:

G ++ -Std = C ++ 2A próbka.cc -lpthread -o próbka.exe

Treść artykułu

  • Odłącz () składnię
  • Nazwa wątku na globalnym zakresie
  • Odłączanie się w nazywanym wątku
  • Wniosek

Odłącz () składnię

Składnia odłącza () jest prosta; to jest:

ThreadObject.odłączyć()

Ta funkcja elementu obiektu wątku zwraca void. ThreadObject to obiekt wątku wątku, którego funkcja działa. Gdy funkcja wątku jest uruchomiona, wątek jest nazywany wątkiem wykonującym.

Nić można odłączyć dopiero po połączeniu; W przeciwnym razie wątek jest już w stanie odłączonym.

Niejednoznaczność odłączania się w ciele nić wywołania

W poniższym programie nazywany wątek jest odłączony w korpusie wątku wywołującego:

#włączać
#włączać
#włączać
za pomocą przestrzeni nazw Std;
String Globl = String („Na Ziemi!");
void func (String st)
String Fin = „Living” + ST;
Cout <
int main ()

Thread Thr (FUNC, GLOBL);
thr.dołączyć();
thr.odłączyć();
powrót 0;

Wyjście z komputera autora w czasie wykonywania brzmiało:

Życie na ziemi!
zakończenie wywołane po rzuceniu instancji „std :: System_error”
co (): nieprawidłowy argument
Przerwane (zrzucone rdzeń)

Właściwa oczekiwana wydajność powinna być po prostu:

Życie na ziemi!

Kiedy wątek kończy wykonanie, implementacja uwalnia wszystkie posiadane zasoby. Po dołączeniu wątku korpus wywołania wątku czeka w tym momencie, aż wywołany wątek zakończy swój wykonanie, wówczas korpus wywołania wątku kontynuuje własne wykonanie.

Problem obecności dalszej wydajności polega na tym, że chociaż nazywany wątek mógł wykonać swoje zadanie, jego zasoby nie zostały odebrane, ale funkcja odłączania () spowodowała kontynuowanie wykonywania ciała funkcji wywołania. W przypadku braku funkcji DEACT () nazywany wątek byłby zakończony, a także wszystkie jej zasoby; a wyjście byłaby prostym oczekiwanym jednodmietem.

Aby przekonać czytelnika, rozważ następujący program, który jest taki sam jak powyższe, ale z wypowiedziami dołączonymi () i dystansu ():

#włączać
#włączać
#włączać
za pomocą przestrzeni nazw Std;
String Globl = String („Na Ziemi!");
void func (String st)
String Fin = „Living” + ST;
Cout <
int main ()

Thread Thr (FUNC, GLOBL);
// Thr.dołączyć();
// Thr.odłączyć();
powrót 0;

Dane wyjściowe z komputera autora to:

zakończenie wywoływane bez aktywnego wyjątku
Przerwane (zrzucone rdzeń)

Funkcja main () przebiegła do końca, nie czekając na to, że wątek coś zrobi. I tak wątek nie mógł wyświetlić swojego wyjścia.

Nazwa wątku na globalnym zakresie

Wątek można utworzyć w globalnym zakresie. Poniższy program ilustruje to:

#włączać
#włączać
za pomocą przestrzeni nazw Std;
wątek th;
void func ()
Cout <<"the first line" <Cout <<"the second line" <
int main ()

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

Wyjście to:

Pierwsza linia
druga linia

Przed funkcją func () jest zdefiniowany w programie; Jest stwierdzenie,

wątek th;

który instaluje wątek, thr. W tym momencie THR nie ma odpowiedniej funkcji. W funkcji Main () pierwszym stwierdzeniem jest:

thr = wątek (func);

Po prawej stronie tego instrukcji tworzy wątek bez nazwy i przypisuje wątek do zmiennej wątku, Thr Thr. W ten sposób THR nabywa funkcję. Następne stwierdzenie dołącza do nazywanego wątku.

Odłączanie się w nazywanym wątku

Lepszym sposobem na oddzielenie wątku jest to, aby to zrobić w korpusie o nazwie nić. W takim przypadku obiekt wątku musiałby zostać utworzony w globalnym zakresie, jak pokazano powyżej. Wówczas stwierdzenie odłączające się będzie w korpusie wywołanego wątku, gdzie powinno odbywać się odłączanie. Poniższy program ilustruje to:

#włączać
#włączać
za pomocą przestrzeni nazw Std;
wątek th;
void func ()
Cout <<"the first line" <thr.odłączyć();
Cout <<"the second line" <
int main ()

thr = wątek (func);
thr.dołączyć();
Cout <<"main() function line" <powrót 0;

Wyjście to:

Pierwsza linia
druga linia
main () linia funkcyjna

W czasie wykonywania nie wydano żadnego komunikatu o błędzie. Instrukcja łączenia () spodziewała się, że wątek zostanie wykonany, zanim nadwozie funkcji Main () będzie kontynuowane. Stało się to pomimo faktu, że zwany wątek został oderwany w środku jego wykonania, z oświadczeniem,

thr.odłączyć();

I tak funkcja Main () (główny wątek) trwała po zakończeniu wywołanego wątku, a wszystkie jej zasoby zostały opublikowane przez implementację. W drugiej połowie wywołanego wątku wywołany wątek został już odłączony, chociaż wątek wywołany wciąż czekał.

Program zaczyna się od włączenia biblioteki iostream dla obiektu Cout. Następnie jest włączenie biblioteki wątków, co jest koniecznością. Następnie występuje instancja wątku, Thr, bez funkcji. Funkcja, której użyje, jest zdefiniowana tuż po. Ta funkcja ma odłączone instrukcje obiektu, Thr w jego ciele.

W ciele funkcyjnym Main () pierwsza instrukcja tworzy wątek funkcji, ale bez nazwy. Ten wątek jest następnie przypisywany do Thr. Tak więc Thr ma teraz funkcję, z zaletą, że został stworzony w globalnym zakresie, aby można było go zobaczyć w FUNC ().

Następne stwierdzenie łączy się z organem funkcyjnym funkcji main () do nazywanego wątku. Wątek został wywołany w pierwszej instrukcji funkcji Main (). W tym momencie nadwozie Main () czeka na to, że nazywany wątek biegnie do końca i wszystkie jego zasoby, choć zostało oderwane na środku. Funkcja Join () wykonuje swój obowiązek, o ile wszystko w zwanym wątku jest uzasadnione.

I tak wykonanie trwa do głównej funkcji po tym, jak nazywany wątek został pomyślnie opuścił, zgodnie z przewidywaniami (z całymi jego zasobami). Dlatego,

„Main () linia funkcyjna”

jest wysyłane po wszystkich wyjściach o nazwie wątku.

Wniosek

Odłączanie wątku oznacza, że ​​wywoływany wątek może nadal wykonywać, a zwany wątek może również nadal wykonywać. To znaczy wątek wywoławczy nie nadal czeka (blok) po dołączeniu. Może to zwiększyć prędkość obu wątków, umożliwiając im bieganie równolegle, a tym samym zwiększenie prędkości całego programu. W takim przypadku najlepiej odłączyć wątek w jego ciele, gdzie komunikacja między nimi nie będzie już wystąpić. Ponadto, aby to osiągnąć, niech zmienna wątków zostanie utworzona w globalnym zakresie bez jej funkcji. W funkcji Main () programu C ++, anonimowy wątek z funkcją zainteresowania można utworzyć i przypisać do zmiennej wątku. Ten krok wywołuje funkcję wątku, a więc wywołuje wątek.

Tak więc, po instrukcji odłączania, oświadczenie Join () nie odgrywa już normalnej roli oczekiwania (blokowanie wątku wywoławczego), choć nadal może czekać. Nie zaleca się oddzielenia wywołanego wątku od wątku wywołania.