Si të konfiguroni telefonat inteligjentë dhe PC. Portali informativ

Shtojca. Bazat e ActionScript

Për të qenë në gjendje të zbatohet logjika në program, përdoren operatorë të kushtëzuar. Konceptualisht, këta operatorë mund të përfaqësohen si pika nodale, deri në të cilat programi bën zgjedhjen në cilin nga drejtimet e mundshme për të ecur përpara. Për shembull, duhet të përcaktoni nëse një variabël arg përmban një numër pozitiv ose negativ dhe të shfaqni mesazhin përkatës në ekran. Për ta bërë këtë, mund të përdorni deklaratën if (nëse), e cila kryen kontrolle të ngjashme.

Në rastin më të thjeshtë, sintaksa për një deklaratë të dhënë if është si më poshtë:

nëse (shprehje)

Nëse vlera e parametrit "shprehje" është "e vërtetë", deklarata ekzekutohet, përndryshe ai anashkalohet nga programi. Duhet të theksohet se "shprehja" është një shprehje e kushtëzuar në të cilën kontrollohet një kusht. Tabela 2.1 paraqet variante të shprehjeve të thjeshta logjike të pohimit if.

Tabela 2.1. Shprehje të thjeshta Boolean

Le të japim një shembull të përdorimit të operatorit if bronkial. Programi i mëposhtëm ju lejon të përcaktoni shenjën e ndryshores së futur.

Listimi 2.1. Programi i parë për përcaktimin e shenjës së numrit të futur.

#përfshi
int main ()
{
noton x;
printf ("Fut një numër:");
scanf (“% f”, & x);
nëse (x> = 0)

Kthimi 0;
}

Analiza e tekstit të programit të dhënë tregon se dy operatorë të kushtëzuar mund të zëvendësohen me një duke përdorur konstruksionin

nëse (shprehje)

që interpretohet në atë mënyrë. Nëse "shprehja" është e vërtetë, atëherë ekzekutohet "deklarata1", përndryshe ekzekutohet "deklarata2". Le të rishkruajmë shembullin e dhënë më parë të përcaktimit të shenjës së një numri duke përdorur këtë ndërtim.

Listimi 2.2. Programi i dytë për përcaktimin e shenjës së numrit të futur.

#përfshi
int main ()
{
noton x;
printf ("Fut një numër:");
scanf (“% f”, & x);
if (x printf (“Numri i futur% f është negativ. \ n”, x);
tjetër
printf (“Numri i futur% f është jo negativ. \ n”, x);

Kthimi 0;
}

Në shembujt e paraqitur, pas deklaratave if dhe else, ekziston vetëm një funksion printf (). Në rastet kur duhet të shkruhet më shumë se një operator kur plotësohet një kusht, duhet të përdoren kllapa kaçurrelë, d.m.th. përdorni një konstrukt si

nëse (shprehje)
{

}
tjetër
{

Duhet të theksohet se pas fjalës kyçe else, mund të vendosni zyrtarisht edhe një deklaratë të kushtit if, si rezultat, marrim një ndërtim edhe më fleksibël të tranzicioneve të kushtëzuara:

nëse (shprehja 1)
ndryshe nëse (shprehja 2)
tjetër

Lista 2.3 tregon një program që zbaton konstruktin e fundit të degës së kushtëzuar.

Listimi 2.3. Programi i tretë për përcaktimin e shenjës së numrit të futur.

#përfshi
int main ()
{
noton x;
printf ("Fut një numër:");
scanf (“% f”, & x);
if (x printf (“Numri i futur% f është negativ. \ n”, x);
ndryshe nëse (x> 0)
printf (“Numri i futur% f është pozitiv. \ n”, x);
tjetër
printf (“Numri i futur% f është jo negativ. \ n”, x);

Kthimi 0;
}

Deri më tani, ne kemi konsideruar kushte të thjeshta si x && - logjike DHE
|| - logjik OSE
! - JO logjike

Kushtet më komplekse mund të krijohen bazuar në këto tre operacione logjike. Për shembull, nëse ka tre variabla exp1, exp2 dhe exp3, atëherë ato mund të përbëjnë konstruktet logjike të paraqitura në tabelë. 2.2.

Tabela 2.2. Shembull i shprehjeve të përbëra boolean

Ashtu si veprimet e shumëzimit dhe mbledhjes në matematikë, veprimet logjike DHE OSE JO, gjithashtu kanë përparësitë e tyre. Operacioni NR ka prioritetin më të lartë, d.m.th. një operacion i tillë kryhet fillimisht. Operacioni AND ka një prioritet më të ulët dhe në fund operacioni OR ka përparësinë më të ulët. Këto prioritete duhet të merren parasysh gjatë hartimit të kushteve komplekse. Për shembull, gjendja

if (4 6 || 5 testohet në këtë mënyrë. Nëse 4 6 OSE 5 if (4 6 || 5 Deklarata if e bën më të lehtë shkrimin e programeve në të cilat ju duhet të zgjidhni midis një numri të vogël opsionesh të mundshme. Megjithatë, ndonjëherë një program duhet të zgjedhë një opsion nga shumë të mundshmet. Formalisht, ju mund të përdorni ndërtimin if else if ... else. Megjithatë, në shumë raste rezulton të jetë më i përshtatshëm për të përdorur deklaratën e ndërprerës C ++. sintaksa e këtij operatori është si më poshtë:

ndërprerës (ndryshueshëm)
{
konstantja e rastit 1:

Konstanta e rastit 2:

...
default:

Ky operator kontrollon në mënyrë sekuenciale për barazinë e ndryshores me konstantet pas rastit të fjalës kyçe. Nëse asnjë nga konstantet nuk është e barabartë me vlerën e ndryshores, atëherë ekzekutohen deklaratat pas fjalës default. Deklarata switch ka veçorinë e mëposhtme. Supozoni se vlera e ndryshores është e barabartë me vlerën e konstantës1 dhe pohimet pas fjalës kyçe të rastit të parë janë ekzekutuar. Pas kësaj, ekzekutimi i programit do të vazhdojë duke kontrolluar variablin për barazinë e konstantës2, e cila shpesh çon në humbje të panevojshme të burimeve kompjuterike. Për të shmangur këtë situatë, duhet të përdorni deklaratën break për ta zhvendosur programin në deklaratën tjetër pas ndërrimit.

Lista 2.4 tregon një shembull të programimit të një deklarate të ndërprerësit të kushtëzuar.

Listimi 2.4. Një shembull i përdorimit të deklaratës switch.

#përfshi
int main ()
{
int x;
printf ("Fut një numër:");
scanf (“% d”, & x);
çelësi (x)
{
rasti 1: printf ("Numri 1 u fut \ n"); pushim;
rasti 2: printf ("Numri 2 u fut \ n"); pushim;
parazgjedhja: printf ("Numri tjetër u fut \ n");
}
char ch;
printf ("Fut një karakter:");
scanf ("% c", & ch);
ndërprerësi (ch)
{
case ‘a’: printf (“U fut karakteri a \ n”); pushim;
rasti 'b': printf ("Karakteri b \ n u fut"); pushim;
default: printf ("Një karakter tjetër \ n futur");
}
kthimi 0;
}

Ky shembull demonstron dy raste të ndryshme përdorimi për deklaratën switch. Në rastin e parë, analizohet shifra e futur, në të dytën, analizohet karakteri i futur. Duhet të theksohet se ky operator mund të bëjë një zgjedhje vetëm në bazë të barazisë së argumentit të tij me një nga vlerat e rasteve të listuara, d.m.th. kontrollimi i shprehjeve si x

Ju mund të ruani njohuri për bashkëbiseduesit ose ndonjë informacion tjetër tekstual. Tani, kur shkruani shabllone, mund të përdorni 13 variabla me një qëllim të paracaktuar dhe 100 "falas", të cilat pronarët e informacionit mund t'i përdorin sipas gjykimit të tyre.
Variablat me një objektiv të caktuar kanë emra kuptimplotë. Për shembull, % emri_përdoruesËshtë një variabël i krijuar për të ruajtur emrin e bashkëbiseduesit. Emri i saj përdor fjalët angleze përdorues ("përdorues") dhe emër ("emër"). Variabla të tillë përdoren në mënyrë aktive nga zhvilluesit kur krijojnë një bazë të modeleve standarde të informacionit, në bazë të të cilave krijohen të gjitha informacionet e përdoruesit në projekt.
Jetëgjatësia e variablave të tillë nuk është e kufizuar; vlerat e tyre mbahen mend dhe ruhen midis bisedave të veçanta.

Çfarë shkruhet në shabllone Shembull dialogu
Mbaje mend emrin:
$ Emri im është *
# Gëzohem që u njohëm. [% emri_përdorues = "[* 1]"]
Një mysafir: Emri im është Vasya
Inf: Takohen një herë.
Ne shfaqim emrin e bashkëbiseduesit në përgjigje infa:
$ Mirupafshim, inf.
# Mirupafshim, [% user_name]
Një mysafir: Mirupafshim, inf.
Inf: Mirupafshim, Vasya.
Ne zgjedhim përgjigjen në varësi të vlerës së ndryshores % user_name:
$ E mbani mend emrin tim?
# (Sigurisht. Ju jeni [% user_name].)
# (Jo. Nuk më tregove emrin tënd.)
Një mysafir: A e mbani mend emrin tim?
Inf: Sigurisht. Ti je Vasya.
ose
Një mysafir: A e mbani mend emrin tim?
Inf: Nr. Nuk ma the emrin.
Ne nuk duam të ruajmë më emrin e bashkëbiseduesit, ne rivendosim variablin
$ Ti je budalla.
# Kaq, nuk jam më shok me ty dhe emrin të kam harruar. [% emri_përdorues = ""]
Një mysafir: Ju jeni një budalla.
Inf: Kjo është ajo, unë nuk jam më shok me ju dhe kam harruar emrin tuaj.

Caktimi i një vlere një ndryshoreje dhe zerimi i një ndryshoreje

Mund t'i caktoni një vlerë një ndryshoreje ose ta vendosni atë në zero në përgjigjet e infa.

Sintaksë:[ndryshore % = "vlera"]
Komanda e caktimit të ndryshoreve është gjithmonë e rrethuar me kllapa katrore, të cilat janë simbole shërbimi këtu. Vlera e një variabli është gjithmonë e mbyllur në thonjëza.
Shembuj të caktimit të vlerës:
$ Unë bëj rock and roll.
# Zili. INF-të nuk mund të kërcejnë [% var1 = "vallëzimi"]

$ * urrej * vallëzim *
$ * valle * urrej *
$ * mos valle *
# Është për të ardhur keq. Nëse do të isha njeri, do të kërceja patjetër. [% var1 = "nuk i pëlqen kërcimi"]

$ Unë jam ** vjeç.
# Mosha e ftohtë! [% mosha e përdoruesit = "[* 1]"]

Një shembull i vendosjes së një ndryshoreje në zero:
$ Nuk dua të flasësh për moshën time.
# Çfarëdo që të thoni [% user_age = ""]

Caktimi i një vlere një ndryshoreje duke përdorur funksionin set

Funksioni grup ("Argument1", "Argument2", "Argument3") zëvendëson Argumentin2 në vend të tij dhe ia cakton vlerën variablit të specifikuar në Argumentin1. Argument3 parazgjedhur për një varg bosh. Nëse e specifikoni atë ndryshe nga një varg bosh, atëherë asnjë tekst nuk do të zëvendësohet për funksionin e vendosur dhe do të caktohet vetëm vlera e ndryshores.

Për shembull,
$ emri im është **
# Më vjen mirë që u njohëm, [@set ("user_name", "[@ (" [* 1] ")]")]!

Një mysafir: emri im është Vasya
Inf: Gëzuar që u njohëm, Vasya!

Ose:
$ emri im është **
# Do të kujtoj emrin tënd. [@set ("emri_përdorues", "[@ (" [* 1] ")]", "1")]

$ * cili është * emri im *
# Ju jeni [% user_name].

Një mysafir: Emri im është Lena
Inf: Unë do të kujtoj emrin tuaj.
Një mysafir: pra si është emri im?
Inf: Ti je Lena.

Dalja e vlerës së një ndryshoreje në përgjigjen infa

Në mënyrë që inf të "tingëllojë" vlerën e ndryshores në përgjigje, ju vetëm duhet të shkruani këtë variabël në përgjigje.
Sintaksë:[%ndryshueshme]
Kërkohen kllapa katrore.

Shembull:
$ Mirupafshim, robot!
# Mirupafshim [% user_name]!

Variabla e kushtëzuar mund të përdoret për të zbatuar marrëdhëniet e sinkronizimit të përmendura më sipër: fillim-fillim (CC), mbarim-fillim (FS), fillim-mbarim (SF) dhe mbarim-mbarim (FF). Kjo marrëdhënie mund të ekzistojë midis fijeve të proceseve të njëjta ose të ndryshme. Listimet 5.4 dhe 5.5 tregojnë shembuj të zbatimit të marrëdhënieve të sinkronizimit FS dhe FF. Çdo shembull përcakton dy mutexes. Një mutex përdoret për të sinkronizuar aksesin në të dhënat e përbashkëta dhe tjetri përdoret për të sinkronizuar ekzekutimin e kodit.

// Listimi 5.4. Marrëdhëniet e sinkronizimit të FS ndërmjet

// dy fije

pthread_t ThreadA, ThreadB;

pthread_cond_t Ngjarja;

i pavlefshëm * punëtor 1(i pavlefshëm * X) (

për (int Count = l; Numërimi

pthread_mutex_lock (& ​​Mutex);

pthread_mutex_unlock (& ​​Mutex);

nëse (numri == 50) (

pthread_cond_signal (& Ngjarje);

i pavlefshëm * punëtor 2(i pavlefshëm * X) (

pthread_mutex_lock (& ​​'EventMutex);

pthread_cond_wait (& Ngjarje, & EventMutex);

për (int Count = 1; Numërimi

pthread_mutex_lock (& ​​Mutex);

Numri = Numri + 20;

pthread_mutex_unlock (& ​​Mutex);

cout "" Ekzekutimi i funksionit worker2 ka përfunduar." "Endl; kthimi (0);

ndër kryesore(int argc, char * argv) (

pthread_mutex_init (& Mutex, NULL);

pthread_mutex_init (& EventMutex, NULL);

pthread_cond_init (& Ngjarje, NULL);

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

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

Lista 5.4 tregon një shembull të një zbatimi të sinkronizimit FS. ThreadA nuk mund të përfundojë derisa të fillojë ThreadB. Nëse Numri bëhet 50, ThreadA ia sinjalizon këtë ThreadB. Tani mund të vazhdojë ekzekutimin deri në fund ThreadB nuk mund të fillojë ekzekutimin derisa të marrë një sinjal nga ThreadA. ThreadB përdor një objekt EventMutex në lidhje me variablin e kushtëzuar Event. Objekti Mutex përdoret për të sinkronizuar aksesin për të shkruar vlerën e ndryshores së përbashkët Number. Një detyrë mund të përdorë mutexe të shumta për të sinkronizuar ngjarje të ndryshme dhe për të hyrë në seksione kritike.

Një shembull i zbatimit të marrëdhënieve të sinkronizimit FF është paraqitur në Listën 5.5.

// Listimi 5.5. Marrëdhëniet e sinkronizimit FF ndërmjet // dy thread-eve

pthread_t ThreadA, ThreadB;

pthread_mutex_t Mutex, EventMutex;

pthread_cond_t Ngjarja;

i pavlefshëm * punëtor (i pavlefshëm * X) (

për (int Count = l; Numërimi

pthread_mu tex_l ock (& ​​· Mutex);

pthread_mutex_unlock (& ​​Mutex);

cout "" workerl: numri është "

pthread_mutex_lock (& ​​'EventMutex), -

cout "" Funksioni workerl është në pritje. "" Endl;

pthread_cond_wait (& Ngjarje, & EventMutex);

pthread_mutex_unlock (& ​​'EventMutex);

i pavlefshëm * punëtor2 (i pavlefshëm * X) (

për (int Count = l; Numërimi

pthread_mutex_lock (& ​​Mutex);

Numri = Numri * 2;

pthread_mutex_unlock (& ​​Mutex);

cout "" worker2: numri është "" Numri "endl;

pthread_cond_signal (& Ngjarje);

cout "" Funksioni worker2 dërgoi një sinjal "" endl; return (0);

int kryesore (int argc, char * argv) (

pthread_mutex_init (& Mutex, NULL);

pthread_mutex_init (& EventMutex, NULL);

pthread_cond_init (& Ngjarje, NULL);

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

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

Në Listimin 5.5, ThreadA nuk mund të përfundojë derisa ThreadB të përfundojë. ThreadA duhet të qarkullojë 10 herë dhe ThreadB duhet të qarkullojë 100. ThreadA do të përfundojë përsëritjet e saj përpara ThreadB, por do të presë derisa ThreadB të sinjalizojë përfundimin e saj.

Marrëdhëniet kohore CC dhe SF nuk mund të zbatohen në këtë mënyrë. Këto metoda përdoren për të sinkronizuar poret unë jam koha e ekzekutimit unë jam proceset.

TAU - teoria e kontrollit automatik

TS - sistemi teknik

ОУ - objekt kontrolli

UU - pajisje kontrolli

SU - sistemi i kontrollit

IO - organ ekzekutiv

IU - pajisje ekzekutive

D - sensor

OS - reagime

PC - raporti i transferimit

PF - funksioni i transferimit

APFC - përgjigja e frekuencës amplitudë-fazë

Përgjigja e frekuencës - karakteristikë amplitudë-frekuencë

LFCH - karakteristikë logaritmike amplitudë-frekuencë

Karakteristikë e frekuencës së fazës - karakteristikë e frekuencës së fazës

2. Simbolet e variablave dhe funksioneve bazë

x(t) - sinjali hyrës i elementit CS, sinjali dalës i OS dhe CS (vlera e kontrolluar)

y(t) Është sinjali dalës i elementit CS, sinjali hyrës i OS (veprimi i kontrollit)

x s ( t) Është ndikimi i vendosjes së sistemit të kontrollit

z(t) A është efekti shqetësues në sistemin e kontrollit

(t) - sinjal gabimi (mospërputhje) në sistemin e kontrollit

1(t) - veprim me një hap

(t) - veprim i vetëm impuls

x m ,y m- vlerat e amplitudës së sinjaleve x(t) dhe y(t)

fq - Operatori Laplace, operatori i diferencimit

 - frekuenca rrethore, operatori i transformimit Furier

X(fq) - imazh i vazhdueshëm i sinjalit x(t) sipas Laplace

X(j) - shfaqja e sinjalit të vazhdueshëm x(t) sipas Furierit

k - Lidhje PC (ose lidhje lidhjesh)

W(fq) - Lidhja PF (ose lidhja e lidhjeve)

W(j) - AFC e një lidhjeje (ose lidhje e lidhjeve)

A() - AFC e një lidhjeje (ose lidhje e lidhjeve)

 () - karakteristikë e frekuencës së fazës së një lidhjeje (ose lidhjes së lidhjeve)

F ( R) - PF e sistemit të kontrollit të mbyllur

h(t) - funksion kalimtar (karakteristik) i një lidhjeje ose sistemi kontrolli

w(t) - funksion impuls (peshë) (karakteristik) i një lidhjeje ose CS

PREZANTIMI

Teoria e kontrollit automatik (TAU)- një disiplinë shkencore, lënda e së cilës janë proceset e informacionit që ndodhin në sistemet e kontrollit të objekteve teknike dhe teknologjike. TAU zbulon modelet e përgjithshme të funksionimit të sistemeve automatike të natyrave të ndryshme fizike dhe, në bazë të këtyre modeleve, zhvillon parimet e ndërtimit të sistemeve të kontrollit me cilësi të lartë.

Kur studiojnë proceset e kontrollit në TAU, ato abstraktohen nga tiparet fizike dhe të projektimit të sistemeve dhe në vend të sistemeve reale marrin parasysh modelet e tyre adekuate matematikore. Sa më saktë (më plotësisht) modeli matematik t'i korrespondojë proceseve fizike që ndodhin në një sistem real, aq më i përsosur do të jetë sistemi i parashikuar i kontrollit.

Metodat kryesore të kërkimit në TAU janë modelimi matematik, teoria e ekuacioneve diferenciale të zakonshme, llogaritja operacionale dhe analiza harmonike. Le të hedhim një vështrim të shpejtë në secilën prej tyre.

Metoda e modelimit matematik, duke kombinuar një shumëllojshmëri të gjerë metodash dhe teknikash për përshkrimin dhe paraqitjen e objekteve dhe fenomeneve fizike, mund të paraqitet në mënyrë skematike, me kusht duke përdorur teknikën më të përdorur - një imazh grafik i një objekti të thjeshtë me një sinjal hyrës. x(t) dhe një sinjal dalës y(t), në formën e një drejtkëndëshi (Fig. B. 1, a). Simboli A brenda drejtkëndëshit nënkupton ndonjë operator matematikor (funksion, integral, etj.) që lidh sinjalet hyrëse dhe dalëse që ndryshojnë në kohë.

Oriz. NË 1. Paraqitja skematike e metodave matematikore të përdorura në TAU

Teoria e ekuacioneve diferenciale të zakonshme, duke u fokusuar në aspektet fizike dhe aplikimet e zgjidhjeve të marra, shërben si bazë metodologjike kryesore e TAU, dhe vetë ekuacionet diferenciale të zakonshme janë forma më e përgjithshme dhe më e plotë e përshkrimit matematikor të elementeve dhe sistemeve të kontrollit. Ekuacionet diferenciale lidhen me variablat hyrëse dhe dalëse që ndryshojnë në kohë dhe derivatet e tyre. Në rastin më të thjeshtë, ekuacioni diferencial ka formën

dy(t)/dt=f[x(t),y(t)]. (NE 1)

Metoda e llogaritjes operacionale, e cila bazohet në transformimin Laplace

(NE 2)

ju lejon të algjebrizoni ekuacionet diferenciale - shkoni te të ashtuquajturat ekuacione të operatorit që lidhin imazhet X(fq) dhe Y(fq) të sinjaleve hyrëse dhe dalëse përmes funksionit të transferimit W(fq) (fig. B. 1, b)

W(fq)=Y(fq)/X(fq). (NË 3)

Metoda e analizës harmonike bazohet në transformimin Furier të njohur nga kursi i matematikës, i cili ka formën

(NË 4)

Duke përdorur transformimin Fourier (V. 4), gjenden imazhet X(j) dhe Y(j) sinjalet hyrëse dhe dalëse x(t) dhe y(t) që karakterizon spektrat e frekuencës së këtyre sinjaleve. Imazhet e sinjaleve Fourier janë të lidhura (Figura B. 1, v) funksioni i transferimit të frekuencës

W(j) = Y (j) / X (j). (NË 5)

Të katër metodat, të paraqitura shkurtimisht më sipër, formojnë aparatin matematikor të TAU. Mbi bazën e tij, është zhvilluar një kompleks i metodave "veta" të TAU, të paraqitura në këtë kurs.

TAU së bashku me teorinë e ndërtimit dhe funksionimit të elementeve të sistemeve të kontrollit (sensorë, rregullatorë, aktuatorë) formon një degë më të gjerë të shkencës - automatizimin. Automatizimi, nga ana tjetër, është një nga degët e kibernetikës teknike. Kibernetika teknike studion sisteme komplekse të automatizuara të kontrollit për proceset teknologjike (APCS) dhe ndërmarrjet (APCS), të ndërtuara duke përdorur kompjuterë kontrolli (CFM).

Kibernetika teknike, së bashku me ato biologjike dhe socio-ekonomike, është pjesë përbërëse e kibernetikës, të cilën themeluesi i saj, matematikani amerikan N. Wiener, e përcaktoi në vitin 1948 si shkencë e kontrollit dhe komunikimit në sistemet teknike dhe organizmat e gjallë.

Rregullatorët e parë industrialë u shfaqën midis 1765 dhe 1804. (I. Polzunov, J. Watt, J. Jacquard).

Studimet e para teorike të rregullatorëve u shfaqën në periudhën 1868-1893. (J. Maxwell, I. Vyshnegradsky, A. Stodola). Shkencëtari dhe inxhinieri rus I.A.Vyshnegradskii kreu një sërë studimesh shkencore në të cilat motori me avull dhe rregullatori i tij u analizuan fillimisht me metoda matematikore si një sistem i vetëm dinamik. Veprat e A. A. Andronov, V. S. Kulebakin, I. N. Voznesensky, B. V. Bulgakov, A. A. Feldbaum, B. N. Petrov, N. N. Krasov luajtën një rol të rëndësishëm në formimin e shkollës ruse të TAU. , AA Voronova, Ya. Z. Tsypkina, VS Pu. ...

Në Fig. NË 2.

Oriz. NË 2. Zhvillimi i përmbajtjes dhe metodologjisë së teorisë së menaxhimit

Aktualisht, TAU, së bashku me seksionet më të fundit të teorisë së menaxhimit të përgjithshëm (kërkimi i operacioneve, inxhinieria e sistemeve, teoria e lojës, teoria e radhës), luan një rol të rëndësishëm në përmirësimin dhe automatizimin e kontrollit të proceseve teknologjike dhe industrive.

Variablat e kushtëzuar

Një variabël kushti (condvar - shkurt për variablin e kushtit) përdoret për të bllokuar një thread për çdo kusht gjatë ekzekutimit të një seksioni kritik të kodit. Kushti mund të jetë aq kompleks sa ju pëlqen dhe nuk varet nga ndryshorja e kushtëzuar. Sidoqoftë, një variabël kushti duhet të përdoret gjithmonë në lidhje me një mutex për të testuar një kusht.

Variablat e kushtëzuar mbështesin funksionet e mëposhtme:

Duke pritur për një variabël të kushtëzuar (prit) ( pthread_cond_wait ());

Zhbllokimi i një transmetimi të vetëm (sinjal) ( pthread_cond_signal ())

Zhbllokimi i transmetimit të shumëfishtë (transmetim) ( pthread_cond_broadcast ()),

Këtu është një shembull i një përdorimi tipik të një ndryshoreje kushti:

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

ndërsa (! kusht arbitrar) (

pthread_cond_wait (& cv, & m);

pthread_mutex_unlock (& ​​m);

Në këtë shembull, kapja e mutex ndodh përpara se të kontrollohet kushti. Kështu, kushti i kontrolluar vlen vetëm për fillin aktual. Për sa kohë që ky kusht është i vërtetë, ky seksion kodi bllokohet në thirrjen e pritjes derisa një thread tjetër të kryejë një operacion të zhbllokimit të fijeve të vetme ose të shumëfishta në një variabël kushti.

Cikli while në shembullin e mësipërm kërkohet për dy arsye. Së pari, standardet posix nuk garantojnë që nuk ka zgjime të rreme (për shembull, në sistemet me shumë procesor). Së dyti, nëse një thread tjetër ndryshon kushtin, ju duhet ta ritestoni atë për t'u siguruar që ndryshimi plotëson kriteret e pranuara. Kur një thread në pritje është i bllokuar, mutex i lidhur me variablin e kushtëzuar lëshohet në mënyrë atomike nga funksioni pthread_cond_wait () në mënyrë që një thread tjetër të mund të hyjë në një seksion kritik të kodit të programit.

Fillimi që kryen një zhbllokim të vetëm në thread do të zhbllokojë fillin me prioritet më të lartë që është në radhë në variablin e kushtit. Një operacion i shumëfishtë i zhbllokimit të thread-ve zhbllokon të gjitha thread-ët e vendosur në radhë në një variabël të kushtëzuar. Muteksi i lidhur me variablin e kushtëzuar çlirohet nga filli i zhbllokuar atomikisht me përparësinë më të lartë. Pas përpunimit të një seksioni kritik të kodit, ky thread duhet të lëshojë mutex.

Një lloj tjetër operacioni duke pritur për një variabël të kushtëzuar ( pthread__cond_timedwair ()) ju lejon të caktoni një afat kohor. Në fund të kësaj periudhe, filli i pritjes mund të zhbllokohet.

Barrierat

Një pengesë është një mekanizëm sinkronizimi që ju lejon të koordinoni punën e disa fijeve ndërvepruese në atë mënyrë që secila prej tyre të ndalet në një pikë të caktuar ndërsa pret fijet e tjera përpara se të vazhdojë punën e saj.

Ndryshe nga funksioni pthreadjoin () në të cilën një fije pret që një fill tjetër të përfundojë, pengesa i detyron fijet takohen në një pikë të caktuar. Pasi numri i specifikuar i fijeve të arrijë barrierën e caktuar, të gjitha këto tema do të zhbllokohen dhe do të vazhdojnë punën e tyre. Barriera krijohet duke përdorur funksionin pthread_barrier_init ():

#përfshi

pthread_barrier_init (pthread_barrier_t * barrierë, konst pthread_barrierattr_t * attr, numërim int i panënshkruar);

Si rezultat i ekzekutimit të këtij kodi, krijohet një barrierë në adresën e dhënë (treguesi i barrierës është në argumentin e barrierës) dhe me atributet e vendosura nga argumenti attr. Argumenti numërimi specifikon numrin e thread-ve për të thirrur pthread_barrier_wait ().

Pasi të krijohet barriera, çdo thread thërret funksionin pthread_barrier_wait (), duke sinjalizuar kështu përfundimin e këtij veprimi:

#përfshi

int pthread_barrier_wait (pthread_barrier_t "pengesë);

Kur filli thërret funksionin pthread_barrier_wait (), ai bllokon deri në numrin e thread-ve që është specifikuar nga funksioni pthread_barrier_init (), nuk do të thërrasë funksionin pthread_jbarrier_wait () dhe, në përputhje me rrethanat, nuk do të bllokohet. Pasi numri i specifikuar i thread-eve thërret funksionin pthread_barrier_wait (), të gjitha hapen njëkohësisht.

#përfshi

#përfshi

#përfshi

#përfshi

barriera pthread_barrier_t; // objekt sinkronizimi i tipit "barrier".

kryesore () // injoroni argumentet

time_t tani; // krijoni një barrierë me një kundërvlerë 3

pthread_barrier_init (& barrier, NULL, 3); // filloni dy threads - threadl dhe thread2

pthread_create (NOLL, NOLL, threadl, NULL); // threads threadl dhe thread2 janë ekzekutuar

pthread_create (NDLL, NDLL, thread2, NDLL); // prisni për përfundimin

printf ("main () në pritje të barrierës në% s", ctime (& tani));

pthread_barrier_wait (& barrier); // pas kësaj pike të tre thread-et përfundojnë

printf ("barriera në mainO e bërë në% s", ctime (& tani));

threadl (i zbrazët * nuk përdoret)

koha (& tani); // kryej llogaritjet

printf ("threadl duke filluar në% s", ctime (& tani)); // pauzë

pthread_barrier_wait (& barrier); // pas kësaj pike të tre thread-et përfundojnë

printf ("barriera në threadl () bërë në% s", ctime (& tani));

thread2 (i pavlefshëm * jo__përdorur)

koha (& tani); // kryej llogaritjet

printf ("thread2 duke filluar në% s", ctime (& tani)); // pauzë

pthread_barrier_wait (& barrier);

// pas kësaj pike përfundojnë të tre thread-at

printf ("barriera në thread2 () bërë në% s", ctime (& tani));

Në shembullin nga lista, filli kryesor krijon një pengesë, pas së cilës fillon të numërojë numrin e fijeve të bllokuara në barrierë për sinkronizim. Në këtë rast, numri i fijeve të sinkronizuara vendoset në 3: filli kryesor () , filli1 () dhe filli 2 ().

Thread1 () dhe thread2 () janë nisur. Për qartësi, vendoset një pauzë në transmetim për të simuluar procesin e llogaritjes. Për të kryer sinkronizimin, thread-i kryesor bllokohet në barrierë dhe pret një zhbllokim që ndodh pasi dy thread-et e tjerë nuk e kanë bashkuar atë në këtë pengesë.



Flokët në pritje

Bllokimet e gjumit funksionojnë në mënyrë të ngjashme me variablat e kushtëzuar, me përjashtim të disa detajeve. Ashtu si variablat e kushtëzuar duke pritur për bravë ( pthread_sleepon_lock ()) mund të përdoret për të bllokuar një thread derisa një kusht të bëhet i vërtetë (i ngjashëm me ndryshimin e vlerës së një vendndodhjeje memorie). Por ndryshe nga variablat e kushtëzuar (të cilat duhet të ekzistojnë për çdo kusht që testohet), bllokimet në pritje aplikohen në një mm.tekst dhe një ndryshore të kushtëzuar të krijuar në mënyrë dinamike, pavarësisht nga numri i kushteve që testohen. Numri maksimal i variablave të kushtëzuar në fund të fundit është i barabartë me numrin maksimal të thread-eve të bllokuara.

Artikujt kryesorë të lidhur