This is an old revision of the document!


Curs 09 - Sincronizare

Demo-uri

Pentru parcurgerea demo-urilor, folosim arhiva aferentă. Demo-urile rulează pe Linux. Descărcăm arhiva folosind comanda

wget http://elf.cs.pub.ro/so/res/cursuri/curs-09-demo.zip

și apoi decomprimăm arhiva

unzip curs-09-demo.zip

și accesăm directorul rezultat în urma decomprimării

cd curs-09-demo/

Acum putem parcurge secțiunile cu demo-uri de mai jos.

Nevoie de acces exclusiv

Dorim să urmărim ce se întâmplă în cazul în care avem date partajate într-un mediu multithread. Pentru aceasta accesăm subdirectorul list-excl/; urmărim conținutul fișierelor thread-list-app.c și list.c. Este vorba de o aplicație care lucrează cu liste înlănțuite într-un mediu multithreaded. Vom observa că există riscul ca datele să fie corupte, fiind necesară sincronizare.

Compilăm fișierele folosind make. Rezultă două fișiere în format executabil: thread-list-app și thread-list-app-mutex.

Programul thread-list-app-mutex folosește intern un mutex pentru sincronizare. Pentru aceasta folosim macro-ul USE_MUTEX pe care îl definim în fișierul Makefile.

Ca să urmărim ce se întâmplă cu o aplicație multithreaded cu date partajate, rulăm de mai multe ori programul thread-list-app, până la obținerea unei erori:

./thread-list-app

Dacă nu dă eroare, putem actualiza în fișierul thread-list-app.c macro-urile NUM_THREADS și NUM_ROUNDS la alte valori (probabil mai mari). Apoi recompilăm folosind make și rulăm din nou programul thread-list-app.

Eroare este cauzată de coruperea pointerilor din lista înlănțuită a programului. Datele sunt accesate concurent, iar în absența sincronizării, vor fi corupte.

Soluția este să folosim un mutex pentru protejarea accesului la listă, lucru realizat în programul thread-list-app-mutex. Dacă vom rula de mai multe ori programul thread-list-app-mutex, nu vom obține niciodată eroare. Avem acces exclusiv la datele partajate deci am rezolvat problema coruperii datelor din cauza accesului concurent neprotejat.

Consum de timp mutex și spinlock

Dorim să investigăm overheadul produs când folosim spinlock-uri și mutex-uri pentru acces exclusiv. Pentru aceasta accesăm subdirectorul spinlock-mutex/; urmărim conținutul fișierului spinlock-mutex.c. Acest fișiere folosește spinlock-uri sau mutex-uri pentru asigurarea accesului exclusiv.

Compilăm cele două programe folosind make. Rezultă două fișiere în format executabil: spinlock și mutex.

  • Intrați în directorul spinlock-mutex/.
  • Consultați fișierul spin.c.
    • Urmăriți efectul macro-ului USE_SPINLOCK.
  • Consultați fișierul Makefile.
    • Observați unde este definit, ca opțiune de compilare, macro-ul USE_SPINLOCK.
  • Folosiți comanda make pentru a obține două executabile: spin și mutex.
  • Rulați cele două executabile prin comanda time pentru a contabiliza timpul de rulare:
    time ./spin
    time ./mutex
    • Care comandă a durat mai mult? De ce?
    • De ce comanda ./spin nu petrece foarte mult în kernel space (system timesys în output-ul time)?

Race condition (TOCTTOU)

Dorim să urmărim cum se manifestă o condiție de cursă de tipul TOCTTOU (time of check to time of use). Pentru aceasta accesăm subdirectorul tocttou/; urmărim conținutul fișierului tocttou.c. Fișierul simulează o problemă producător consumator în care producătorul produce câte NUM_ITEMS_PRODUCER elemente, iar consumatorul consumă câte NUM_ITEMS_CONSUMER elemente; dacă un consumator nu poate consuma elemente, își încheie execuția.

Compilăm programul folosind make. Rezultă fișierul tocttou în format executabil.

Deadlock

Dorim să urmărim cum se manifestă un deadlock. Pentru aceasta accesăm subdirectorul deadlock/; urmărim conținutul fișierului deadlock.c. Fișierul are o implementare didactică pentru două tipuri de thread-uri care obțin în ordine diferită două mutex-uri.

Compilăm programul folosind make. Rezultă fișierul deadlock în format executabil.

Așteptare nedefinită

Dorim să urmărim cum se manifestă o problemă de așteptare nedefinită (indefinite wait). Pentru aceasta accesăm subdirectorul indefinite-wait/; urmărim conținutul fișierului indefinite-wait.c. Fișierul are o implementare nefucțională pentru problema producători-consumatori, lucru care conduce la așteptare nedefinită.

Compilăm programul folosind make. Rezultă fișierul indefinite-wait în format executabil.

Granularitate regiune critică

Dorim să urmărim cum se comportă un program atunci când diferă dimensiunea regiunii critice folosită pentru acces exclusiv. Pentru aceasta accesăm subdirectorul granularity/; urmărim conținutul fișierului granularity.c. Fișierul are o implementare didactică în care mai multe thread-uri accesează o regiune critică.

Compilăm programul folosind make. Rezultă două fișiere în format executabil: granuarity-fine și granularity-coarse. Fișierului executabil granularity-fine îi corespunde o regiune critică de mică dimensiune, dar accesată des; fișierului executabil granularity-coarse îi corespunde o regiune critică de dimensiune mai mare, dar accesată rar.

În cadrul codului, folosirea unei granularități fine sau nu este indicată de macro-ul GRANULARITY_TYPE inițializat în Makefile.

Pentru a vedea impactul tipului de granularitate, rulăm cele două fișiere în format executabil și măsurăm timpul de rulare:

/usr/bin/time ./granularity-fine
/usr/bin/time ./granularity-coarse

Observăm că dureaza semnificativ mai mult rularea executabilului cu granularitate fină. Acest lucru se întâmplă pentru că regiunea critică pe care acesta o protejează este mic, iar cea mai mare parte din timp o va consuma în operațiile cu mutex-ul (lock contention). Observăm acest lucru și din numărul mare de schimbări de context (voluntare sau nevoluntare).

În general preferăm granularitate fină pentru regiunile critice (adică regiuni critice de mică dimensiune); dar granularitatea fină poate înseamna operații foarte dese pe mutex (lock contention). De aceea este recomandat ca folosirea granularității fine să fie echilibrată de un număr redus de thread-uri care să dorească să acceseze la un moment dat regiunea critică, pentru a genera cât mai puțină încărcare (contention) pe mutex.

so/cursuri/curs-09.1397497640.txt.gz · Last modified: 2014/04/14 20:47 by razvan.deaconescu
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0