Ce se întâmplă cu o detașată fir când main() ieșiri?

Presupun că'm a începe un std::fir "și apoi" detașați (), deci firul continuă de executare, chiar dacă std::fir că, odată ce a reprezentat ea, iese din sfera de aplicare.

Se presupune în continuare că programul nu are un protocol de încredere pentru aderarea la detașat thread1, deci detașat încă firul se execută atunci când main() ieșiri.

Eu nu pot găsi nimic în standard (mai precis, în N3797 C++14 proiect), care descrie ceea ce ar trebui să se întâmple, nici 1.10 nici 30.3 conțin formularea pertinentă.

1 un Alt, probabil, echivalent, întrebarea este: "poate o decomandat firul fi vreodată s-a alăturat din nou", deoarece, indiferent de protocol're inventarea să se alăture, de semnalizare parte ar trebui să fie făcut în timp ce firul a fost încă rulează, și sistemul de OPERARE scheduler putea decide pentru a pune firul la culcare timp de o oră imediat după semnalizare fost efectuate cu nici o cale pentru primirea end pentru a detecta sigur că firul de fapt terminat.

În cazul în care rulează din main () cu fire desprinse de funcționare este definit comportamentul, atunci _any_ utilizare a std::thread::detașați() este nedefinit comportamentul excepția cazului în care firul principal nu iese2.

Astfel, în criză de main() cu detașat fire execută trebuie să aibă defined efecte. Întrebarea este: where (în C++ standard, nu POSIX, nu sistemul de OPERARE google docs, ...) sunt acele efecte definite.

2 O decomandat fir nu poate fi alăturat (în sensul de std::thread::join()). Ai can așteptați pentru rezultatele desprinse din fire (de exemplu, prin intermediul unui viitor de la std::packaged_task`, sau printr-o numărare semafor sau un steag și o condiție variabilă), dar asta nu't o garanție că thread a terminat executing. Într-adevăr, dacă ai pus semnalizare parte în destructor de primul automată a obiectelor de fir, acolo voi fi, în general, codul (destructori) care rulează after semnalizare cod. Dacă sistemul de OPERARE programe de firul principal de a consuma rezultat și de ieșire înainte de a detașat fir finisaje de funcționare a spus destructori, ce va^Wis definite să se întâmple?

Comentarii la întrebare (1)
Soluția

Răspunsul la întrebarea inițială "ce se întâmplă cu o detașată fir atunci când main() iese" este:

Ea continuă de funcționare (pentru că standardul nu't spune este oprit), și că's bine-definite, atâta timp cât nu se atinge nici (automat|thread_local) variabile de alte fire, nici obiecte statice.

Acest lucru pare să fie permis pentru a permite firului de manageri ca obiecte statice (notă în [de bază.începe.pe termen]/4 spune cât mai mult, datorită @dyp pentru pointer).

Problemele apar atunci când distrugerea de obiecte statice a terminat, pentru că atunci execuție intră într-un regim numai în cazul în care codul este permis în semnal stivuitoare pot executa ([de bază.începe.pe termen]/1, 1 propoziție). Din biblioteca standard C++, care este de numai <atomic> biblioteca (*[suport.de execuție]/9, 2-a propoziție*). În special, faptul că—în general—*exclude*condition_variable(l&#39;s aplicare definit, fie că este de a salva de a utiliza într-un handler de semnal, deoarece&#39;s nu fac parte din`).

Dacă nu'am derulată stack-ul tău la acest punct, l's greu pentru a vedea cum pentru a evita comportament nedefinit.

Răspunsul la a doua întrebare "poate detașat fire vreodată fi alăturat din nou" este:

Da, cu *_at_thread_exit familia de funcții (notify_all_at_thread_exit(),std::promise::set_value_at_thread_exit()`, ...).

După cum sa menționat în nota de subsol [2] de întrebare, de semnalizare o variabila de conditie sau un semafor sau o atomice contra nu este suficient să se alăture unui detașat de subiect (în sensul de a asigura că la sfârșitul execuției sale are-s-a întâmplat înainte primirea de spus semnalizare de un fir de așteptare), pentru că, în general, nu va fi mai mult cod de executat, de exemplu, o notify_all() de o condiție variabilă, în special distrugatorii de masini automate si thread-obiecte locale.

Rularea de semnalizare ca ultimul lucru pe care firul nu (după destructori de automate și thread-obiecte locale are-s-a întâmplat) e ce `_at_thread_exit familia de funcții a fost proiectat pentru.

Deci, în scopul de a evita nedefinit comportamentul în absența punerii în aplicare a garanțiilor de mai sus ce standard impune, aveți nevoie pentru a (manual) alăturați-vă o decomandat fir cu un `_at_thread_exit funcția de a face semnalizare sau face detașat fir de execut numai cod care ar fi în siguranță pentru un semnal handler, de asemenea.

Comentarii (7)

Detasarea Fire

Potrivit std::thread::detașa:

Separă fir de execuție din thread obiect, care să permită execuția să continue în mod independent. Orice resursele alocate vor fi eliberat după ce firul iese.

De pthread_detach:

pthread_detach() funcția indică la punerea în aplicare că de depozitare pentru firul poate fi recuperat atunci când acel fir se termină. Dacă firul nu și-a reziliat, pthread_detach() nu că pentru a termina. Efectul de mai multe pthread_detach() apeluri pe aceeași țintă firul este nespecificat.

Detasarea fire este în principal pentru economisirea de resurse, în cazul în care cererea nu este nevoie să așteptați pentru un fir pentru a termina (de exemplu daemon, care trebuie să ruleze până la terminarea procesului):

  1. Pentru a elibera aplicație mâner lateral: Unul poate să o std::fir obiect ieși din domeniul de aplicare fără a se alătura, ceea ce duce în mod normal la un apel la std::termina() pe distrugere.
  2. Pentru a permite sistemului de OPERARE să curatare fir de resurse specifice (TCB) automat de îndată ce firul iese, pentru că am specificat în mod explicit, că nu suntem't de interesat în aderarea la firul mai târziu, astfel, nu se poate alătura o deja detașat fir.

Uciderea Fire

Comportamentul la terminarea procesului este aceeași ca și cea pentru firul principal, care ar putea cel puțin să prind niște semnale. Indiferent dacă sunt sau nu alte fire se pot ocupa de semnale nu este atât de important, ca s-ar putea alătura sau de a rezilia alte fire în firul principal's signal handler de invocare. (Întrebare legate)

După cum sa menționat deja, [orice subiect, fie detașat sau nu, va muri cu procesul pe cele mai multe sisteme de operare](http://en.wikipedia.org/wiki/Thread_(de calcul)). Procesul în sine poate fi reziliat prin ridicarea unui semnal, de apel de ieșire () sau prin revenirea din funcția principală. Cu toate acestea, C++11 nu poate și nu încearcă să definească exact comportamentul de fond al sistemului de OPERARE, întrucât dezvoltatorii de Java VM, cu siguranță poate fi rezumat astfel de diferențe-o anumită măsură. AFAIK, proces exotice și filetare modele sunt de obicei găsite pe platformele vechi (pentru care C++11, probabil, a câștigat't fi portat) și diferite sisteme integrate, care ar putea avea un speciale și/sau lingvistic limitat bibliotecă de punere în aplicare și, de asemenea, limitată suport lingvistic.

Fir Suport

Daca firele nu sunt't sprijinit std::thread::get_id() ar trebui să se întoarcă un invalid id-ul (default construite std::fir::id), ca acolo's un simplu proces, care nu are nevoie de un fir de obiect pentru a rula și constructorul de o std::fir ar trebui să arunce o std::system_error. Acesta este modul în care am înțeles C++11 în legătură cu ziua de azi's sisteme de operare. Dacă nu's un sistem de OPERARE cu suport filetat, care nu't spawn un fir principal în procesele sale, lasă-mă să știu.

Controlul Fire

Dacă este nevoie de a păstra controlul asupra unui fir pentru buna opririi, o poate face folosind primitive de sincronizare și/sau un fel de steaguri. Cu toate acestea, În acest caz, stabilind un shutdown de pavilion, urmat de un join este modul în care am prefera, deoarece nu's nici un punct în creșterea complexității prin detasarea fire, ca resursele ar fi eliberat, în același timp, în orice caz, în cazul în care câțiva octeți de std::fir obiect vs. complexitate mai mare și, eventual, mai primitive de sincronizare ar trebui să fie acceptabil.

Comentarii (2)

Soarta fir după ieșirile de program este nedefinit comportament. Dar un sistem de operare modern va curăța toate subiectele create de procesul de închidere.

Atunci când detașarea un std::fir`, aceste trei condiții va continua să dețină:

  1. *asta nu mai deține orice subiect
  2. joinable() va fi întotdeauna egal cu "false"
  3. get_id() va fi egal cu std::fir::id()
Comentarii (4)

Luați în considerare următorul cod:


#include 
#include 
#include 
#include 

void thread_fn() {
  std::this_thread::sleep_for (std::chrono::seconds(1)); 
  std::cout 
Comentarii (1)

Când firul principal (care este, firul care execută funcția main ()) încheie, atunci procesul se termină și toate celelalte fire opri.

Referință: https://stackoverflow.com/a/4667273/2194843

Comentarii (0)

Pentru a permite alte fire pentru a continua executarea, firul principal ar trebui să termina de asteptare pthread_exit (), mai degrabă decât de ieșire(3). L's bine să utilizați pthread_exit în principal. Când pthread_exit este utilizat, firul principal se va opri de executare și va rămâne în zombie(defunct) stare până când toate celelalte fire de ieșire. Dacă utilizați pthread_exit în firul principal, nu poate obține statutul de alte fire și nu poate face curat-up pentru alte fire (ar putea fi realizat folosind pthread_join(3)). De asemenea, l'e mai bine să se detașeze fire(pthread_detach(3)), astfel încât firul resursele sunt eliberate în mod automat pe fir de reziliere. Resursele partajate nu va fi eliberat până când toate firele de ieșire.

Comentarii (2)