C ++ Bli med på tråden

C ++ Bli med på tråden
Tråder er som underprogrammer til et program. Og slik ville de løpe uavhengig med mindre de ble sammen med. Å sammenstille betyr at en tråd vil løpe til den når et bestemt punkt og deretter stopper og venter på at en annen tråd skal fullføre utførelsen (til slutt); Før den fortsetter sin egen henrettelse. På det punktet der den første tråden stopper, er det en Join -uttalelse. En tråd kan ringe en annen tråd. Det er tråden som ringer, som blir med. Den kalt tråden blir ikke med.

Sammenføyning eksisterer fordi tråder må kommunisere med hverandre. Etter at endringen har funnet sted, kan den kalt tråd. Dette er en form for synkronisering.

Denne artikkelen forklarer to måter å bli med på tråder. Det begynner med en illustrasjon av hva en tråd er.

Artikkelinnhold

  • Tråd
  • Bli med i en tråd
  • Future :: Get ()
  • Konklusjon

Tråd

Tenk på følgende program:

#inkludere
ved hjelp av navneområdet STD;
void fn2 ()
cout << "function 2" << '\n';

void fn1 ()
cout << "function 1" << '\n';

int main ()

/ * Noen utsagn */
retur 0;

FN1 (), FN2 () og Main () er funksjoner på toppnivå, selv om Main () er en nøkkelfunksjon. Tre tråder kan fås fra disse tre funksjonene på toppnivå. Følgende veldig enkelt korte program, er en naturlig tråd:

#inkludere
ved hjelp av navneområdet STD;
int main ()

/ * Noen utsagn */
retur 0;

Hovedfunksjonen () oppfører seg som en tråd. Det kan betraktes som hovedtråden. Det trenger ikke å bli innkapslet i noen instantiering fra trådklassen. Så det forrige programmet med funksjoner på toppnivå som inkluderer Main () -funksjonen er fremdeles en tråd. Følgende program viser hvordan de to funksjonene, FN1 () og FN2 () kan konverteres til tråder, men uten noen Join -setning:

#inkludere
#inkludere
#inkludere
ved hjelp av navneområdet STD;
String globl1 = streng ("so,");
streng globl2 = streng ("være det!");
void fn2 (streng st2)
Streng globl = globl1 + st2;
cout << globl << endl;

void fn1 (streng st1)
globl1 = "ja. " + ST1;
tråd Thr2 (Fn2, Globl2);

int main ()

tråd Thr1 (FN1, Globl1);
/ * Noen utsagn */
retur 0;

Programmet begynner med inkludering av iostream -biblioteket for cout -objektet. Da er trådbiblioteket inkludert. Å inkludere trådbiblioteket er et must; Slik at programmereren ganske enkelt bare vil instantisere et trådobjekt fra trådklassen ved hjelp av en funksjon på toppnivå, bortsett fra Main () -funksjonen.

Etter det er strengbiblioteket inkludert. Dette biblioteket forenkler bruken av strenglitteraler. Den første uttalelsen i programmet insisterer på at ethvert navn som brukes er fra C ++ Standard navneområdet med mindre annet er angitt.

De to neste uttalelsene erklærer to globale strengobjekter med sine bokstaver. Strengobjektene kalles globl1 og globl2. Det er FN1 () -funksjonen og FN2 () -funksjonen. FN2 () -funksjonens navn vil bli brukt som et av argumentene for å instantisere tråden, Thr2, fra trådklassen. Når en funksjon blir instantiert på denne måten, kalles funksjonen; Og den henrettes. Når FN2 () -funksjonen kalles, sammenkobler den strenglitteralene til Globl1 og Globl2 å ha “Så, det være seg!”. Globl2 er argumentet til FN2 ().

Navnet på FN1 () -funksjonen brukes som et argument for å fremheve tråden, Thr1, fra trådklassen. I løpet av denne instantieringen kalles FN1 (). Når det heter, går den foran strengen, “Så det være det!”Med" Ja. ", å ha" ja. Så være det!", Som er utgangen for hele trådprogrammet.

Hoved () -funksjonen, som er hoved () tråden, instantierer tråden, Thr1 fra trådklassen, med argumentene FN1 og Globl1. I løpet av denne instantieringen kalles FN1 (). Funksjonen, FN1 () er den effektive tråden for objektet, Thr1. Når en funksjon kalles, skal den løpe fra begynnelsen til slutten.

Thr1, som effektivt er FN1 (), instantierer tråden, Thr2, fra trådklassen, med argumentene FN2 og Globl2. I løpet av denne instantieringen kalles FN2 (). Funksjonen, Fn2 () er den effektive tråden for objektet, Thr2. Når en funksjon kalles, skal den løpe fra begynnelsen til slutten.

Hvis leseren bruker, G ++ -kompilatoren, kan han teste dette tråderprogrammet, for C ++ 20 -sammenstilling, med følgende kommando:

G ++ -STD = C ++ 2A Temp.CPP -LPTHREAD -O TEMP

Forfatteren gjorde dette; Kjørte programmet og hadde utdataene:

avsluttet kalt uten et aktivt unntak
Abortert (kjernen dumpet)

Det er mulig å ha en feilaktig produksjon som dette, med riktig utgang av "ja. Så være det!", slisset innenfor. Imidlertid er alt som fremdeles er uakseptabelt.

Problemet med denne feilaktige utgangen er at tråder ikke ble sammenføyd. Og slik, trådene opererte uavhengig, noe som førte til forvirring. Løsningen er å bli med Thr1 til hovedtråden, og siden Thr1 kaller Thr2, akkurat som hovedtråden kaller Thr1, må Thr2 kobles til THR1. Dette er illustrert i neste avsnitt.

Bli med i en tråd

Syntaksen for å gå sammen med en tråd til den samtalede tråden er:

threadobj.bli med();

hvor join () er en medlemsfunksjon av et trådobjekt. Dette uttrykket må være inne i kroppen til den samtaletråden. Dette uttrykket må være inne i kroppen av anropsfunksjonen, som er en effektiv tråd.

Følgende program er det ovennevnte programmet gjentatt, men med kroppen til hovedtråden som går sammen med Thr1, og kroppen til Thr1 som blir med i Thr2:

#inkludere
#inkludere
#inkludere
ved hjelp av navneområdet STD;
String globl1 = streng ("so,");
streng globl2 = streng ("være det!");
void fn2 (streng st2)
Streng globl = globl1 + st2;
cout << globl << endl;

void fn1 (streng st1)
globl1 = "ja. " + ST1;
tråd Thr2 (Fn2, Globl2);
Thr2.bli med();

int main ()

tråd Thr1 (FN1, Globl1);
Thr1.bli med();
/ * Noen utsagn */
retur 0;

Legg merke til ventestillingene, der sammenføyningsuttalelsene er satt inn i programmet. Utgangen er:

"Ja. Så være det!”

Uten sitatene, som forventet, rent og tydelig, entydig ”. THR2 trenger ikke noen sammenføyningsuttalelse i kroppen; det kaller ingen tråd.

Så kroppen av den samtaletråden blir med den kalte tråden.

Future :: Get ()

C ++ standardbiblioteket har en underbibliotek kalt fremtid. Denne underbiblioteket har en klasse som heter Future. Biblioteket har også en funksjon som heter Async (). Klassen, fremtid, har en medlemsfunksjon som heter Get (). I tillegg til hovedrollen, har denne funksjonen effekten av å slå sammen to funksjoner som kjører samtidig eller parallelt. Funksjonene trenger ikke å være tråder.

Async () -funksjonen

Legg merke til at trådene fremfor alle returnerer tomrom. En tråd er en funksjon som er under kontroll. Noen funksjoner returnerer ikke tomrom, men returnerer noe. Så noen tråder returnerer noe.

Async () -funksjonen kan ta en toppnivåfunksjon som et argument og kjøre funksjonen samtidig eller parallelt med anropsfunksjonen. I dette tilfellet er det ingen tråder, bare en anropsfunksjon og en kalt funksjon som kalles et argument til async () -funksjonen. En enkel syntaks for async -funksjonen er:

Future Futobj = async (fn, fnargs)

Async -funksjonen returnerer et fremtidig objekt. Det første argumentet her, for async-funksjonen, er navnet på toppnivåfunksjonen. Det kan være mer enn ett argument etter dette. Resten av argumentene er argumenter for toppnivåfunksjonen.

Hvis funksjonen på toppnivå returnerer en verdi, vil den verdien være medlem av det fremtidige objektet. Og dette er en måte å etterligne en tråd som returnerer en verdi.

Future :: Get ()

Async -funksjonen returnerer et fremtidig objekt. Dette fremtidige objektet har returverdien av funksjonen som er et argument for async -funksjonen. For å oppnå denne verdien, må Get () medlemsfunksjonen til det fremtidige objektet brukes. Scenariet er:

fremtidig futobj = async (fn, fnargs);
Type Futobj.få();

Når get () -funksjonen kalles, venter kroppen til anropsfunksjonen (blokker), til async -funksjonen har returnert verdien. Etter det fortsetter resten av uttalelsene under get () -uttalelsen å utføre.

Følgende program er den ovennevnte, der det er opprettet noen tråd offisielt, og i stedet for sammenføyningserklæringen, er Get () -klæringen blitt brukt. Async () -funksjonen har blitt brukt til å simulere en tråd. De to funksjonene på toppnivå er redusert til en. Programmet er:

#inkludere
#inkludere
#inkludere
ved hjelp av navneområdet STD;
String globl1 = streng ("so,");
streng globl2 = streng ("være det!");
String fn (String ST1, String ST2)
streng concat = ST1 + ST2;
return concat;

int main ()

Future FUT = Async (Fn, Globl1, Globl2);
String ret = fut.få(); // main () venter her
Strengresultat = "Ja. " + ret;
cout << result << endl;
retur 0;

Merk at det fremtidige biblioteket, i stedet for trådbiblioteket, er inkludert. Utgangen er:

Ja. Så være det!

Konklusjon

Når det gjelder en sammenføyningsuttalelse, er to funksjoner på toppnivå involvert. Den ene er anropsfunksjonen, og den andre er den kalt funksjonen. I kroppen til anropsfunksjonen er Join -setningen. Disse to funksjonene kan være hver innkapslet i en tråd. Join () medlemsfunksjonen til den kalt tråd. Når Funce () -funksjonen kalles, venter den samtalen tråden på det tidspunktet (blokker) til den kalt tråden er fullført; Før det fortsetter å operere.

Bruk av tråder kan unngås ved å bruke ASYNC () -funksjonen i det fremtidige biblioteket. Denne funksjonen tar en toppnivåfunksjon som et argument og returnerer et fremtidig objekt, som inneholder den returnerte verdien av argumentfunksjonen til ASYNC () -funksjonen. For å oppnå returverdien til funksjonen som et argument, må Get () medlemsfunksjonen til det fremtidige objektet brukes. Når Get () medlemsfunksjonen kalles, venter anropsfunksjonsorganet på det tidspunktet (blokker) til den kalte funksjonen er fullført; Før det fortsetter å operere.