Cum se configurează smartphone-uri și PC-uri. Portal informativ

Apendice. Noțiuni de bază pentru ActionScript

Pentru a putea implementa logica in program se folosesc operatori conditionali. Conceptual, acești operatori pot fi reprezentați ca puncte nodale, ajungând la care programul alege în care dintre direcțiile posibile să meargă mai departe. De exemplu, trebuie să determinați dacă o variabilă arg conține un număr pozitiv sau negativ și să afișați mesajul corespunzător pe ecran. Pentru a face acest lucru, puteți utiliza instrucțiunea if (if), care efectuează verificări similare.

În cel mai simplu caz, sintaxa pentru o declarație if dată este următoarea:

dacă (expresie)

Dacă valoarea parametrului „expresie” este „adevărat”, instrucțiunea este executată, altfel este omisă de program. Trebuie remarcat faptul că „expresie” este o expresie condiționată în care se verifică o anumită condiție. Masa 2.1 prezintă variante ale expresiilor logice simple ale instrucțiunii if.

Tabelul 2.1. Expresii booleene simple

Să dăm un exemplu de utilizare a operatorului de ramificare if. Următorul program vă permite să determinați semnul variabilei introduse.

Lista 2.1. Primul program pentru determinarea semnului numărului introdus.

#include
int main ()
{
float x;
printf („Introduceți un număr:”);
scanf ("% f", & x);
dacă (x> = 0)

Returnează 0;
}

Analiza textului programului dat arată că doi operatori condiționali pot fi înlocuiți cu unul folosind construcția

dacă (expresie)

care este interpretat astfel. Dacă „expresie” este adevărată, atunci „statement1” este executat, în caz contrar „statement2” este executat. Să rescriem exemplul dat anterior de determinare a semnului unui număr folosind această construcție.

Lista 2.2. Al doilea program pentru determinarea semnului numărului introdus.

#include
int main ()
{
float x;
printf („Introduceți un număr:”);
scanf ("% f", & x);
if (x printf („Numărul introdus% f este negativ. \ n”, x);
altfel
printf („Numărul introdus% f este nenegativ. \ n”, x);

Returnează 0;
}

În exemplele prezentate, după instrucțiunile if și else, există o singură funcție printf (). În cazurile în care trebuie să fie scris mai mult de un operator atunci când este îndeplinită o condiție, trebuie folosite acolade, de ex. utilizați un construct ca

dacă (expresie)
{

}
altfel
{

Trebuie remarcat faptul că, după cuvântul cheie else, puteți pune în mod oficial încă o declarație de condiție if, ca urmare, obținem o construcție și mai flexibilă a tranzițiilor condiționate:

dacă (expresia1)
else if (expresia2)
altfel

Lista 2.3 prezintă un program care implementează ultimul construct de ramură condiționată.

Lista 2.3. Al treilea program pentru determinarea semnului numărului introdus.

#include
int main ()
{
float x;
printf („Introduceți un număr:”);
scanf ("% f", & x);
if (x printf („Numărul introdus% f este negativ. \ n”, x);
altfel dacă (x> 0)
printf („Numărul introdus% f este pozitiv. \ n”, x);
altfel
printf („Numărul introdus% f este nenegativ. \ n”, x);

Returnează 0;
}

Până acum, am luat în considerare condiții simple precum x && - AND logic
|| - SAU logic
! - NR logic

Pe baza acestor trei operații logice pot fi generate condiții mai complexe. De exemplu, dacă există trei variabile exp1, exp2 și exp3, atunci ele pot constitui constructele logice prezentate în tabel. 2.2.

Tabelul 2.2. Exemplu de expresii booleene compuse

La fel ca și operațiile de înmulțire și adunare din matematică, operațiile logice ȘI SAU NU, au și ele priorități proprii. Operațiunea NO are cea mai mare prioritate, adică. o astfel de operaţie se execută mai întâi. Operația ȘI are o prioritate mai mică și, în sfârșit, operația SAU are cea mai mică prioritate. Aceste priorități trebuie luate în considerare la elaborarea unor condiții complexe. De exemplu, starea

if (4 6 || 5 este bifat în acest fel. If 4 6 SAU 5 if (4 6 || 5 Instrucțiunea if facilitează scrierea de programe în care trebuie să alegeți între un număr mic de opțiuni posibile. Cu toate acestea, uneori, un program trebuie să selecteze o opțiune dintre multele posibile. În mod formal, puteți utiliza construcția if else if ... else. Cu toate acestea, în multe cazuri se dovedește a fi mai convenabil să utilizați instrucțiunea C ++ switch. sintaxa acestui operator este următoarea:

comutator (variabil)
{
constanta de caz 1:

Caz constant2:

...
Mod implicit:

Acest operator verifică secvenţial pentru egalitatea variabilei cu constantele după cuvântul cheie caz. Dacă niciuna dintre constante nu este egală cu valoarea variabilei, atunci instrucțiunile de după cuvântul default sunt executate. Declarația switch are următoarea particularitate. Să presupunem că valoarea variabilei este egală cu valoarea constantă1 și sunt executate instrucțiunile de după cuvântul cheie primul caz. După aceea, execuția programului va continua prin verificarea variabilei pentru egalitatea constantei2, ceea ce duce adesea la risipa inutilă a resurselor computerului. Pentru a evita această situație, ar trebui să utilizați instrucțiunea break pentru a muta programul la următoarea instrucțiune după comutare.

Lista 2.4 prezintă un exemplu de programare a unei instrucțiuni de comutare condiționată.

Lista 2.4. Un exemplu de utilizare a instrucțiunii switch.

#include
int main ()
{
int x;
printf („Introduceți un număr:”);
scanf („% d”, & x);
comutator (x)
{
cazul 1: printf („Numărul 1 introdus \ n”); break;
cazul 2: printf („Numărul 2 introdus \ n”); pauză;
implicit: printf („Un alt număr introdus \ n”);
}
char ch;
printf („Introduceți un caracter:”);
scanf ("% c", & ch);
comutator (ch)
{
case ‘a’: printf („S-a introdus caracterul a \ n”); pauză;
case ‘b’: printf („Caracterul b \ n introdus”); pauză;
implicit: printf („Un alt caracter \ n introdus”);
}
returnează 0;
}

Acest exemplu demonstrează două cazuri de utilizare diferite pentru instrucțiunea switch. În primul caz se analizează cifra introdusă, în al doilea se analizează caracterul introdus. Trebuie remarcat faptul că acest operator poate face o alegere numai pe baza egalității argumentului său cu una dintre valorile cazului enumerate, i.e. verificarea expresiilor ca x

Puteți stoca cunoștințe despre interlocutori sau orice alte informații text. Acum, când scrieți șabloane, puteți utiliza 13 variabile cu un scop prestabilit și 100 de „gratuite”, pe care proprietarii de informații le pot folosi la discreția lor.
Variabilele cu o anumită țintă au nume semnificative. De exemplu, % nume de utilizator Este o variabilă concepută pentru a stoca numele interlocutorului. Numele ei folosește cuvintele englezești user ("utilizator") și nume ("nume"). Astfel de variabile sunt utilizate în mod activ de către dezvoltatori atunci când creează o bază de șabloane de informații standard, pe baza cărora sunt create toate informațiile despre utilizator în proiect.
Durata de viață a unor astfel de variabile nu este limitată; valorile lor sunt memorate și stocate între conversații separate.

Ce este scris în șabloane Exemplu de dialog
Tine minte numele:
$ Numele meu este *
# Încântat de cunoștință. [% user_name = "[* 1]"]
Un musafir: Numele meu este Vasya
Inf:Întâlnește-te o dată.
Afișăm numele interlocutorului ca răspuns infa:
$ Pa, inf.
# La revedere, [% user_name]
Un musafir: Pa, inf.
Inf: La revedere, Vasya.
Alegem răspunsul în funcție de valoarea variabilei% user_name:
$ Îți amintești numele meu?
# (Desigur. Sunteți [% user_name].)
# (Nu. Nu mi-ai spus numele tău.)
Un musafir:Îți amintești numele meu?
Inf: Cu siguranță. Tu ești Vasya.
sau
Un musafir:Îți amintești numele meu?
Inf: Nu. Nu mi-ai spus numele tău.
Nu mai dorim să stocăm numele interlocutorului, resetăm variabila
$ Esti un prost.
# Așa e, nu mai sunt prieten cu tine și ți-am uitat numele. [% user_name = ""]
Un musafir: Esti nebun.
Inf: Gata, nu mai sunt prieten cu tine si ti-am uitat numele.

Atribuirea unei valori unei variabile și punerea la zero a unei variabile

Puteți atribui o valoare unei variabile sau o puteți seta la zero în răspunsurile infa.

Sintaxă:[% variabilă = „valoare”]
Comanda de atribuire a variabilelor este întotdeauna înconjurată de paranteze drepte, care sunt simboluri de serviciu aici. Valoarea unei variabile este întotdeauna cuprinsă între ghilimele.
Exemple de atribuire a valorii:
$ Fac rock and roll.
# Invidiez. INF nu poate dansa [% var1 = "dancing"]

$ * ura * dans *
$ * dans * ura *
$*nu dansa*
# E pacat. Dacă aș fi om, cu siguranță aș dansa. [% var1 = „nu-i place să danseze”]

$ Am ** ani.
# Vârsta rece! [% user_age = "[* 1]"]

Un exemplu de setare a unei variabile la zero:
$ Nu vreau să vorbești despre vârsta mea.
# Orice ai spune [% user_age = ""]

Atribuirea unei valori unei variabile folosind funcția set

Funcţie set („Argument1”, „Argument2”, „Argument3”)înlocuiește Argument2 în locul său și atribuie valoarea acestuia variabilei specificate în Argument1. Argument3 are implicit un șir gol. Dacă o specificați altfel decât un șir gol, atunci niciun text nu va fi înlocuit pentru funcția set, și numai valoarea variabilei va fi alocată.

De exemplu,
$ numele meu este **
# Mă bucur să te cunosc, [@set ("nume_utilizator", "[@ (" [* 1] ")]")]!

Un musafir: numele meu este Vasya
Inf: Mă bucur să te cunosc, Vasya!

Sau:
$ numele meu este **
# Îmi voi aminti numele tău. [@set ("nume_utilizator", "[@ (" [* 1] ")]", "1")]

$ * care este * numele meu *
# Sunteți [% user_name].

Un musafir: Numele meu este Lena
Inf:Îmi voi aminti numele tău.
Un musafir: deci care este numele meu?
Inf: Tu ești Lena.

Afișarea valorii unei variabile în răspunsul infa

Pentru ca inf să „suneze” valoarea variabilei din răspuns, trebuie doar să scrieți această variabilă în răspuns.
Sintaxă:[%variabil]
Sunt necesare paranteze pătrate.

Exemplu:
$ Pa, robot!
# La revedere [% user_name]!

Variabila condițională poate fi utilizată pentru a implementa relațiile de sincronizare menționate mai sus: start-start (CC), finish-start (FS), start-finish (SF) și finish-finish (FF). Această relație poate exista între fire ale aceluiași proces sau diferite procese. Listările 5.4 și 5.5 prezintă exemple de implementare a relațiilor de sincronizare FS și FF. Fiecare exemplu definește două mutexuri. Un mutex este folosit pentru a sincroniza accesul la datele partajate, iar celălalt este folosit pentru a sincroniza execuția codului.

// Listarea 5.4. Relaţiile de sincronizare FS între

// două fire

pthread_t ThreadA, ThreadB;

pthread_cond_t Eveniment;

nul * muncitor1(nulă * X) (

pentru (int Count = l; Count

pthread_mutex_lock (& ​​​​Mutex);

pthread_mutex_unlock (& ​​​​Mutex);

dacă (Număr == 50) (

pthread_cond_signal (& Eveniment);

nul * muncitor2(nulă * X) (

pthread_mutex_lock (& ​​​​EventMutex);

pthread_cond_wait (& Event, & EventMutex);

pentru (int Count = 1; Count

pthread_mutex_lock (& ​​​​Mutex);

Număr = Număr + 20;

pthread_mutex_unlock (& ​​​​Mutex);

cout "" Execuția funcției worker2 sa încheiat. " „Endl; întoarcere (0);

int principal(int argc, char * argv) (

pthread_mutex_init (& Mutex, NULL);

pthread_mutex_init (& EventMutex, NULL);

pthread_cond_init (& Event, NULL);

pthread_create (& ThreadA, NULL, workerl, NULL);

pthread_create (& ThreadB, NULL, worker2, NULL);

Lista 5.4 prezintă un exemplu de implementare a sincronizării FS. ThreadA nu se poate termina până când ThreadB nu a început. Dacă Number devine 50, ThreadA semnalează acest lucru ThreadB. Acum poate continua execuția până la sfârșit. ThreadB nu poate începe execuția până când nu primește un semnal de la ThreadA. ThreadB folosește un obiect EventMutex împreună cu variabila condițională Event. Obiectul Mutex este folosit pentru a sincroniza accesul pentru a scrie valoarea variabilei partajate Number. O sarcină poate folosi mai multe mutexuri pentru a sincroniza diverse evenimente și pentru a accesa secțiuni critice.

Un exemplu de implementare a relațiilor de sincronizare FF este prezentat în Lista 5.5.

// Listarea 5.5. Relații de sincronizare FF între // două fire

pthread_t ThreadA, ThreadB;

pthread_mutex_t Mutex, EventMutex;

pthread_cond_t Eveniment;

void * workerl (void * X) (

pentru (int Count = l; Count

pthread_mu tex_l ock (& ​​​​Mutex);

pthread_mutex_unlock (& ​​​​Mutex);

cout "" workerl: numărul este "

pthread_mutex_lock (& ​​​​EventMutex), -

cout "" Funcția workerl este în așteptare. "" Endl;

pthread_cond_wait (& Event, & EventMutex);

pthread_mutex_unlock (& ​​​​EventMutex);

void * lucrător2 (void * X) (

pentru (int Count = l; Count

pthread_mutex_lock (& ​​​​Mutex);

Număr = Număr * 2;

pthread_mutex_unlock (& ​​​​Mutex);

cout "" worker2: numărul este "" Numărul "endl;

pthread_cond_signal (& Eveniment);

cout "" Funcția worker2 a trimis un semnal "" endl; return (0);

int main (int argc, char * argv) (

pthread_mutex_init (& Mutex, NULL);

pthread_mutex_init (& EventMutex, NULL);

pthread_cond_init (& Event, NULL);

pthread_create (& ThreadA, NULL, workerl, NULL);

pthread_create (& ThreadB, NULL, worker2, NULL);

În Lista 5.5, ThreadA nu se poate termina până când ThreadB nu se finalizează. ThreadA trebuie să circule de 10 ori și ThreadB trebuie să facă bucla de 100. ThreadA își va finaliza iterațiile înainte de ThreadB, dar va aștepta până când ThreadB semnalează finalizarea sa.

Relațiile de sincronizare CC și SF nu pot fi implementate în acest mod. Aceste metode sunt folosite pentru a sincroniza porii eu sunt timpul de execuție eu sunt proceselor.

TAU - teoria controlului automat

TS - sistem tehnic

ОУ - obiect de control

UU - dispozitiv de control

SU - sistem de control

IO - organ executiv

IU - dispozitiv executiv

D - senzor

OS - feedback

PC - raport de transfer

PF - functie de transfer

APFC - răspuns în frecvență amplitudine-fază

Raspuns in frecventa - caracteristica amplitudine-frecventa

LFCH - caracteristică amplitudine-frecvență logaritmică

Caracteristica fază-frecvență - caracteristică fază-frecvență

2. Simboluri ale variabilelor și funcțiilor de bază

X(t) - semnal de intrare al elementului CS, semnal de ieșire al OS și CS (valoare controlată)

y(t) Este semnalul de ieșire al elementului CS, semnalul de intrare al OS (acțiune de control)

X s ( t) Este influența de setare a sistemului de control

z(t) Este efectul perturbator asupra sistemului de control

(t) - semnal de eroare (nepotrivire) în sistemul de control

1(t) - acțiune cu un singur pas

(t) - acţiune cu un singur impuls

X m ,y m- valorile amplitudinii semnalelor X(t) și y(t)

p - operator Laplace, operator de diferențiere

 - frecvenţă circulară, operator transformată Fourier

X(p) - imagine semnal continuu X(t) conform lui Laplace

X(j) - afişare semnal continuu X(t) conform lui Fourier

k - Link PC (sau conexiuni link)

W(p) - legătură PF (sau conexiune de legături)

W(j) - AFC a unei legături (sau a conexiunii de legături)

A() - AFC a unei legături (sau a conexiunii de legături)

 () - caracteristica de fază-frecvență a unei legături (sau a conexiunii de legături)

F ( R) - PF al sistemului de control închis

h(t) - functie tranzitorie (caracteristica) a unei legaturi sau a unui sistem de control

w(t) - funcția de impuls (greutate) (caracteristică) a unei legături sau CS

INTRODUCERE

Teoria controlului automat (TAU)- o disciplină științifică, al cărei subiect îl reprezintă procesele informaționale care au loc în sistemele de control al obiectelor tehnice și tehnologice. TAU dezvăluie modelele generale de funcționare a sistemelor automate de diferite naturi fizice și, pe baza acestor modele, dezvoltă principiile construirii sistemelor de control de înaltă calitate.

Când studiază procesele de control în TAU, ei fac abstracție de caracteristicile fizice și de proiectare ale sistemelor și, în loc de sisteme reale, iau în considerare modelele lor matematice adecvate. Cu cât modelul matematic corespunde mai precis (mai complet) proceselor fizice care au loc într-un sistem real, cu atât sistemul de control proiectat va fi mai perfect.

Principalele metode de cercetare la UAT sunt modelarea matematică, teoria ecuațiilor diferențiale ordinare, calculul operațional și analiza armonică. Să aruncăm o privire rapidă la fiecare dintre ele.

Metoda modelării matematice, care combină o mare varietate de metode și tehnici de descriere și prezentare a obiectelor și fenomenelor fizice, poate fi reprezentat condiționat, schematic folosind tehnica cea mai frecvent utilizată - o imagine grafică a unui obiect simplu cu un semnal de intrare X(t) și un semnal de ieșire y(t), sub forma unui dreptunghi (Fig. B. 1, A). Simbol Aîn interiorul dreptunghiului înseamnă un operator matematic (funcție, integrală etc.) care conectează semnalele de intrare și de ieșire care se modifică în timp.

Orez. ÎN 1. Reprezentarea schematică a metodelor matematice utilizate în TAU

Teoria ecuațiilor diferențiale ordinare, concentrându-se pe aspectele fizice și aplicațiile soluțiilor obținute, servește drept bază metodologică principală a TAU, iar ecuațiile diferențiale obișnuite în sine sunt cea mai generală și completă formă de descriere matematică a elementelor și sistemelor de control. Ecuațiile diferențiale relaționează variabilele de intrare și ieșire care variază în timp și derivatele lor. În cel mai simplu caz, ecuația diferențială are forma

dy(t)/dt=f[X(t),y(t)]. (ÎN 1)

Metoda de calcul operațional, care se bazează pe transformarea Laplace

(IN 2)

vă permite să algebrizați ecuații diferențiale - mergeți la așa-numitele ecuații de operator care conectează imagini X(p) și Y(p) a semnalelor de intrare și de ieșire prin funcția de transfer W(p) (fig. B. 1, b)

W(p)=Y(p)/X(p). (LA 3)

Metoda analizei armonice se bazează pe transformata Fourier cunoscută din cursul de matematică, care are forma

(LA 4)

Folosind transformata Fourier (V. 4), imaginile sunt găsite X(j) și Y(j) semnale de intrare şi de ieşire X(t) și y(t) care caracterizează spectrele de frecvenţă ale acestor semnale. Imaginile semnalelor Fourier sunt legate (Figura B. 1, v) funcţia de transfer de frecvenţă

W(j) = Y (j) / X (j). (LA 5)

Toate cele patru metode, prezentate pe scurt mai sus, formează aparatul matematic al TAU. Pe baza acestuia, a fost dezvoltat un complex de metode „proprii” de TAU, prezentate în acest curs.

TAU împreună cu teoria construcției și funcționării elementelor sistemelor de control (senzori, regulatoare, actuatoare) formează o ramură mai largă a științei - automatizarea. Automatizarea, la rândul său, este una dintre ramurile ciberneticii tehnice. Cibernetica tehnică studiază sisteme complexe de control automatizat pentru procese tehnologice (APCS) și întreprinderi (APCS), construite cu ajutorul calculatoarelor de control (CFM).

Cibernetica tehnică, alături de cele biologice și socioeconomice, este o parte integrantă a ciberneticii, pe care fondatorul ei, matematicianul american N. Wiener, a definit-o în 1948 drept știința controlului și comunicării în sistemele tehnice și organismele vii.

Primele regulatoare industriale au apărut între 1765 și 1804. (I. Polzunov, J. Watt, J. Jacquard).

Primele studii teoretice ale regulatorilor au apărut în perioada 1868-1893. (J. Maxwell, I. Vyshnegradsky, A. Stodola). Omul de știință și inginerul rus I.A.Vyshnegradskii a efectuat o serie de studii științifice în care motorul cu abur și regulatorul său au fost analizate pentru prima dată prin metode matematice ca un singur sistem dinamic. Lucrările lui A. A. Andronov, V. S. Kulebakin, I. N. Voznesensky, B. V. Bulgakov, A. A. Feldbaum, B. N. Petrov, N. N. Krasov au jucat un rol important în formarea școlii ruse a TAU. , AA Voronova, Ya. Z. Tsypkina, VS Pugacheva ...

Dezvoltarea teoriei moderne de control din așa-numita teorie „clasică”, bazată pe cele patru metode de cercetare de bază ale TAU menționate mai sus, și formarea celor mai noi metode ale acesteia sunt ilustrate schematic în Fig. ÎN 2.

Orez. ÎN 2. Dezvoltarea conținutului și metodologiei teoriei managementului

În prezent, TAU, împreună cu cele mai recente secțiuni ale teoriei generale a managementului (cercetare operațională, ingineria sistemelor, teoria jocurilor, teoria cozilor de așteptare), joacă un rol important în îmbunătățirea și automatizarea controlului proceselor și industriilor tehnologice.

Variabile condiționale

O variabilă de condiție (condvar - prescurtare pentru variabila de condiție) este folosită pentru a bloca un fir pentru orice condiție în timpul execuției unei secțiuni critice de cod. Condiția poate fi atât de complexă pe cât doriți și nu depinde de variabila condiționată. Cu toate acestea, o variabilă de condiție trebuie întotdeauna utilizată împreună cu un mutex pentru a testa o condiție.

Variabilele condiționate acceptă următoarele funcții:

Se așteaptă o variabilă condiționată (așteptați) ( pthread_cond_wait ());

Deblocare un singur flux (semnal) ( pthread_cond_signal ())

Deblocarea fluxurilor multiple (difuzare) ( pthread_cond_broadcast ()),

Iată un exemplu de utilizare tipică a unei variabile de condiție:

pthread_mutex_lock (& ​​​​m); - ...

în timp ce (! condiție arbitrară) (

pthread_cond_wait (& cv, & m);

pthread_mutex_unlock (& ​​​​m);

În acest exemplu, capturarea mutexului are loc înainte ca condiția să fie verificată. Astfel, condiția verificată se aplică numai firului curent. Atâta timp cât această condiție este adevărată, această secțiune de cod blochează apelul de așteptare până când un alt fir de execuție efectuează o operație de deblocare a unui fir de execuție unic sau multiplu pe o variabilă de condiție.

Bucla while din exemplul de mai sus este necesară din două motive. În primul rând, standardele posix nu garantează că nu există false wake (de exemplu, pe sistemele multiprocesor). În al doilea rând, dacă un alt thread modifică condiția, trebuie să-l retestați pentru a vă asigura că modificarea îndeplinește criteriile acceptate. Când un fir în așteptare este blocat, mutex-ul asociat variabilei condiționate este eliberat atomic de funcție pthread_cond_wait () astfel încât un alt thread să poată intra într-o secțiune critică a codului programului.

Firul care efectuează o singură deblocare pe firul de execuție va debloca firul de execuție cu cea mai mare prioritate care se află în coada variabilei de condiție. O operație de deblocare a mai multor fire de execuție deblochează toate firele aflate în coadă pe o variabilă condiționată. Mutexul asociat cu variabila condițională este eliberat de firul deblocat atomic cu cea mai mare prioritate. După procesarea unei secțiuni critice de cod, acest fir trebuie să elibereze mutex-ul.

Un alt tip de operație care așteaptă o variabilă condiționată ( pthread__cond_timedwair ()) vă permite să setați un timeout. La sfârșitul acestei perioade, firul de așteptare poate fi deblocat.

Bariere

O barieră este un mecanism de sincronizare care vă permite să coordonați activitatea mai multor fire care interacționează în așa fel încât fiecare dintre ele să se oprească la un anumit punct în timp ce așteptați alte fire înainte de a-și continua activitatea.

Spre deosebire de funcție pthreadjoin ()în care un fir așteaptă ca un alt fir să se finalizeze, bariera forțează firele întâlni la un moment dat. După ce numărul specificat de fire atinge bariera stabilită, toate aceste fire se vor debloca și își vor continua munca. Bariera este creată folosind funcția pthread_barrier_init ():

#include

pthread_barrier_init (pthread_barrier_t * barieră, const pthread_barrierattr_t * attr, unsigned int count);

Ca urmare a executării acestui cod, se creează o barieră la adresa dată (pointerul către barieră se află în argumentul barieră) și cu atributele setate de argumentul attr. Argumentul count specifică numărul de fire de execuție de apelat pthread_barrier_wait ().

După ce bariera este creată, fiecare fir apelează funcția pthread_barrier_wait (), semnalând astfel finalizarea acestei acțiuni:

#include

int pthread_barrier_wait (pthread_barrier_t „barieră);

Când firul apelează funcția pthread_barrier_wait (), se blochează până la numărul de fire care a fost specificat de funcție pthread_barrier_init (), nu va apela funcția pthread_jbarrier_wait ()și, în consecință, nu vor fi blocate. După numărul specificat de fire apelează funcția pthread_barrier_wait (), toate se deblochează simultan.

#include

#include

#include

#include

pthread_barrier_t barieră; // obiect de sincronizare de tip „barieră”.

main () // ignoră argumentele

time_t now; // creează o barieră cu o valoare a contorului de 3

pthread_barrier_init (& barieră, NULL, 3); // începe două fire - threadl și thread2

pthread_create (NOLL, NOLL, threadl, NULL); // firele threadl și thread2 sunt executate

pthread_create (NDLL, NDLL, thread2, NDLL); // așteptați finalizarea

printf ("principal () așteaptă bariera la% s", ctime (& acum));

pthread_barrier_wait (& barieră); // după acest punct, toate cele trei fire sunt terminate

printf ("barieră în mainO făcută la% s", ctime (& acum));

threadl (void * nu este folosit)

timp (& acum); // efectuează calcule

printf ("threadl care începe la% s", ctime (& acum)); // pauză

pthread_barrier_wait (& barieră); // după acest punct, toate cele trei fire sunt terminate

printf ("barieră în threadl () făcut la% s", ctime (& acum));

thread2 (void * not__used)

timp (& acum); // efectuează calcule

printf ("thread2 care începe la% s", ctime (& acum)); // pauză

pthread_barrier_wait (& barieră);

// după acest punct toate cele trei fire sunt terminate

printf ("barieră în thread2 () făcut la% s", ctime (& acum));

În exemplul din listare, firul principal creează o barieră, după care începe să numere numărul de fire blocate pe barieră pentru sincronizare. În acest caz, numărul de fire sincronizate este setat la 3: fir principal (), fir1 () și fir2 ().

Thread1 () și thread2 () sunt pornite. Pentru claritate, este setată o pauză în flux pentru a simula procesul de calcul. Pentru a efectua sincronizarea, firul principal se blochează pe barieră și așteaptă o deblocare care are loc după ce celelalte două fire nu s-au unit pe această barieră.



Încuietori în așteptare

Blocările Sleepon funcționează într-un mod similar cu variabilele condiționate, cu excepția câtorva detalii. Ca și variabilele condiționate care așteaptă blocări ( pthread_sleepon_lock ()) poate fi folosit pentru a bloca un fir până când o condiție devine adevărată (similar cu schimbarea valorii unei locații de memorie). Dar, spre deosebire de variabilele condiționate (care trebuie să existe pentru fiecare condiție verificată), blocările în așteptare sunt aplicate unui mm.text și unei variabile condiționate create dinamic, indiferent de numărul de condiții testate. Numărul maxim de variabile condiționate este în cele din urmă egal cu numărul maxim de fire blocate.

Top articole similare