Capitolul 7
multithreading
Cu toată atenția sa concentrat pe cursorul mouse-ului, este ușor să uităm că peste - doar o parte a cererii. După apariția cursorului cererea nu ar trebui să fie în mod fundamental diferită de cele de mai sus, astfel încât ar fi de dorit să inserați codul de intrare de la mouse-ul și cursorul în mijlocul de actualizare a aplicației. Și chiar dacă suntem de acord pe acest lucru, deoarece acest cod ar arăta? Acesta ar trebui să verifice în mod constant pentru noi date de la mouse-ul. La detectarea datelor pe care le actualizează cursorul mouse-ului; în caz contrar continuă funcționarea sa normală. Permanent aplicarea lent mouse-ul sondaj și complexitatea structurii sale. O soluție mai bună - divizat aplicația în două sub-sarcini folosind multithreading.
Dacă sunteți deja familiarizați cu conceptul de multi-threading, nu va fi nevoie de această secțiune. Cu toate acestea, pentru incepatori, abordează principalele prevederi care trebuie învățate înainte de a trece la programare. În nici un caz nu trebuie să fie interpretată ca un ghid cuprinzător pentru filetare.
Curente și procese
Sunteți conștienți de ea sau nu, sunteți deja familiarizați cu fire și procese. De fiecare dată când un nou proces este creat atunci când începe programul. Procesul permite programului la tot ce avea nevoie pentru a lucra, inclusiv un fir (fir). Acest flux standard (de asemenea, numit curentul principal - firul primar) este utilizat pentru executarea codului de program. Fluxul principal al unui proces tipic începe cu punctul de intrare (pentru programele bazate pe Windows este funcția WinMain ()) și care urmează să fie efectuate în conformitate cu toate buclele, declarații condiționale și apeluri de funcții continuă. Fluxul principal este completat cu finalizarea procesului.
Cu toate acestea, nimic nu restricționează un flux de proces. MFC sau Win32 instrumente vă permit să creați fire suplimentare, care sunt utilizate în mod obișnuit pentru a efectua sarcini de fundal. Aceste fluxuri suplimentare (numite uneori flux de lucru) funcționează independent de fluxul principal (precum și unele de altele). Fiecare fir are propria stivă, dar resursele de sistem (cum ar fi fișiere și memoria dinamică) sunt împărțite între fire.
De ce multi-threading?
Multithreading este benefic dacă aveți mai multe sarcini care pot (cel puțin parțial) să funcționeze simultan. Cod aplicație multithreaded scris corect pare simplu, pentru că fiecare fir efectuează o anumită sarcină.
Pe de altă parte, aplicarea multi-threaded mai greu de a scrie și de depanare. Va trebui să sincronizeze acces multithreaded la resursele partajate, pentru a evita rezultate imprevizibile, precum și să coordoneze punerea în aplicare a codului dependente, pentru a asigura succesiunea corectă a evenimentelor.
Un ultim punct: pe un singur computer procesor, aplicații multi-threaded nu alerga mai repede decât un singur fir. viteza crește numai pe un calculator multiprocesor cu un sistem multi-operare (de exemplu, Windows NT).
sincronizare fir
Adăugați un nou flux în program este simplu - este mult mai dificil de a organiza executarea și finalizarea, atât de multe funcții sunt API multithreaded proiectate special pentru sincronizarea firului. În această secțiune, vom analiza pe scurt o astfel de sincronizare.
Fluxurile sunt coordonate cu Event-ului (evenimente), care transmit informații despre starea unuia sau mai multor fluxuri. Evenimentul poate fi setat (semnalizate) sau eliminate (unsignaled). Semnificația concretă a evenimentelor poate varia, dar de obicei ele semnal de blocaj de debit.
Blocarea fluxului poate fi imaginat ca o buclă, interoghează continuu anumite variabile logice. Ciclul continuă atâta timp cât variabila nu ia valoarea TRUE. Din punct de vedere tehnic, acest lucru nu este în întregime corectă, deoarece a blocat fluxul de evenimente nu produce sondaje activ. In schimb, el este suspendat, iar sistemul îl elimină din lista de fire activă. Numai după un eveniment de blocare va merge la starea instalat, firul este reluat. În consecință firul blocat cu greu consumă timp CPU.
Blocarea fluxului este cel mai des folosit pentru a proteja resursele partajate de acces concurent de mai multe fire. Mutex (mutex, o reducere a exclud reciproc, adică „exclud reciproc“) este un obiect care poate fi în orice moment deținută de un singur fir, asigurând acces securizat la resursele aferente. Când mutex aparține unui flux, toate celelalte fire care încearcă să-l la dispoziția sa, pentru a elibera mutex blocat.
secțiuni critice (secțiunea critică), cum ar fi mutex, sunt folosite pentru a preveni accesul simultan la o resursă de mai multe fire. Cu toate acestea, în cazul în care mutex poate sincroniza fluxuri interprocese, secțiunea critică este limitată la același flux de proces. Limitarea vitezei este compensată - secțiunea critică este mai rapid decât mutex.
Semafoarelor (semaphore), de asemenea, pot fi utilizate pentru a restricționa accesul la resurse, dar spre deosebire de un mutex sau un semafor a secțiunilor critice permite accesul simultan cu mai multe fire. Numărul maxim de fire în același timp, accesul câștigă la resursa este determinată pentru a crea un semafor. Apoi, se acordă accesul la toate fluxurile de până la numărul lor ajunge la o limită predeterminată. Toate celelalte fire care doresc să acceseze sunt blocate atâta timp cât unul sau mai multe fluxuri care nu mai lucrați cu resursa.
Clasele fluxuri MFC
Pentru programare multi-threaded în Windows, puteți alege dintre clasele de MFC și Win32 funcții de streaming. Microsoft recomandă să utilizați în fluxurile de clasă MFC aplicației. Pentru fire în MFC oferă următoarele clase:
Clasa CWinThread reprezintă un flux separat. Este prezentă în toate aplicațiile, deoarece clasa CWinApp (clasa de baza pentru DirectDrawApp) este derivată din CWinThread. Acest exemplu este principala aplicare CWinThread flux; pentru a adăuga noi fluxuri de lucru, de a crea obiecte CWinThread.
clasa CSyncObject este virtuală. Crearea imediată a cazurilor de această clasă nu sunt permise; ea există numai în scopul de a asigura funcționalitatea claselor derivate. clasa CSyncObject este clasa de baza pentru CEvent. CCriticalSection. CMutex și CSemaphore. obiecte de sincronizare reprezentate de aceste clase, discutate în secțiunea anterioară.
Clasele CSingleLock CMultiLock si folosite pentru a bloca fluxul ca unul sau mai multe evenimente. Clasa CSingleLock blocheaza fluxul înainte de instalarea unui eveniment specific, și CMultiLock - să instaleze unul sau toate evenimentele dintr-un set dat.
Mai târziu, în acest capitol vom folosi clasele CWinThread. CEvent. CCriticalSSection și CMultiLock.