Differences

This shows you the differences between two versions of the page.

Link to this comparison view

so:cursuri:curs-09 [2014/04/19 00:14]
catalin.vasile3004 [Curs 09 - Sincronizare]
so:cursuri:curs-09 [2019/04/15 01:04] (current)
razvan.deaconescu
Line 1: Line 1:
 ====== Curs 09 - Sincronizare ====== ====== Curs 09 - Sincronizare ======
  
-<​html>​ +  * [[http://​elf.cs.pub.ro/​so/​res/​cursuri/​SO%20-%20Curs%2009%20-%20Sincronizare.pdf|Curs 09 - Sincronizare (PDF)]]
-    <iframe src="​http://​docs.google.com/​viewer?​url=http://​elf.cs.pub.ro/​so/​res/​cursuri/​SO_Curs-09.pdf&​embedded=true"​ width="​600"​ height="​480"​ style="​border:​ none;">​ +
-    </​iframe>​ +
-</​html>​+
  
-  * [[http://elf.cs.pub.ro/so/​res/​cursuri/​SO_Curs-09.pdf ​Curs 09 - Sincronizare (PDF)]]+  * [[https://drive.google.com/open?​id=1PCJp2UD0KSuAOFJ9ZMkB_lMhR9jJ4exD7Pgm-vzSrQA|Notițe de curs]]
  
   * Suport curs   * Suport curs
-    * Operating Systems Concepts +    * Operating Systems Concepts ​Essentials 
-      * Capitolul ​- Process Synchronization+      * Capitolul ​- Process Synchronization
     * Modern Operating Systems     * Modern Operating Systems
       * Capitolul 2 - Processes and Threads       * Capitolul 2 - Processes and Threads
         * Secțiunea 2.3 - Interprocess Communication         * Secțiunea 2.3 - Interprocess Communication
     * [[http://​greenteapress.com/​semaphores/​|Allen B. Downey - The Little Book of Semaphores]]     * [[http://​greenteapress.com/​semaphores/​|Allen B. Downey - The Little Book of Semaphores]]
 +    * [[https://​deadlockempire.github.io/​|The Deadlock Empire: Slay dragons, master concurency!]]
 +  * [[http://​elf.cs.pub.ro/​so/​res/​cursuri/​SO_Curs-09.pdf|Curs 09 anterior]]
 +
 +
 +<​html>​
 +  <​center>​
 +    <iframe src="​https://​docs.google.com/​viewer?​url=https://​elf.cs.pub.ro/​so/​res/​cursuri/​SO%20-%20Curs%2009%20-%20Sincronizare.pdf&​embedded=true"​ width="​600"​ height="​480"​ style="​border:​ none;">​
 +    </​iframe>​
 +  </​center>​
 +</​html>​
  
 ===== Demo-uri ===== ===== Demo-uri =====
Line 44: Line 51:
 </​note>​ </​note>​
  
-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.+Eroarea ​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:<​code bash> 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:<​code bash>
Line 58: Line 65:
 Compilăm cele două programe folosind ''​make''​. Rezultă două fișiere în format executabil: ''​spinlock''​ și ''​mutex''​. Compilăm cele două programe folosind ''​make''​. Rezultă două fișiere în format executabil: ''​spinlock''​ și ''​mutex''​.
  
-Cele două fișiere au fost generat ​din același cod sursă (''​spinlock-mutex.c''​),​ după cum a fost definit sau nu macro-ul ''​USE_SPINLOCK''​. Macro-ul îl definim în fișierul ''​Makefile''​.+Cele două fișiere au fost generate ​din același cod sursă (''​spinlock-mutex.c''​),​ după cum a fost definit sau nu macro-ul ''​USE_SPINLOCK''​. Macro-ul îl definim în fișierul ''​Makefile''​.
  
 Pentru a contabiliza timpul de rulare rulăm cele două executabile prin comanda ''​time'':<​code bash> Pentru a contabiliza timpul de rulare rulăm cele două executabile prin comanda ''​time'':<​code bash>
Line 92: Line 99:
 adică o condiție de cursă de tipul TOCTTOU, în care se poate "​infiltra"​ alt thread. Practic este posibil ca două thread-uri să scadă valoarea variabilei ''​num_items''​ deși condiția ar fi trebuit să se întâmple doar pentru unul. Dacă avem o valoare inițială ''​NUM_ITEMS_CONSUMER + 2'',​ atunci există riscul ca mai multe thread-uri să vadă îndeplinită condiția și apoi toate să scadă valoarea variabilei ''​num_items''​ rezultând într-o valoare negativă. adică o condiție de cursă de tipul TOCTTOU, în care se poate "​infiltra"​ alt thread. Practic este posibil ca două thread-uri să scadă valoarea variabilei ''​num_items''​ deși condiția ar fi trebuit să se întâmple doar pentru unul. Dacă avem o valoare inițială ''​NUM_ITEMS_CONSUMER + 2'',​ atunci există riscul ca mai multe thread-uri să vadă îndeplinită condiția și apoi toate să scadă valoarea variabilei ''​num_items''​ rezultând într-o valoare negativă.
  
-O astfel de situația poate duce la un comportament nedeterminst al programului,​ la coruperea datelor, chiar la încheierea cu eroare a programului. Mai mult o astfel de situație poate fi exploatată de un atacator.+O astfel de situație poate duce la un comportament nedeterminst al programului,​ la coruperea datelor, chiar la încheierea cu eroare a programului. Mai mult o astfel de situație poate fi exploatată de un atacator.
  
 Pentru a preveni apariția condițiilor de cursă, trebuie implementată corespunzător sincronizarea accesului. Din păcate, condițiile de cursă pot apărea foarte greu (adică programul să fie greșit dar să meargă **aproape** tot timpul); acest lucru face nedeterminist comportamentul programului și dificilă investigarea problemei. Pentru a preveni apariția condițiilor de cursă, trebuie implementată corespunzător sincronizarea accesului. Din păcate, condițiile de cursă pot apărea foarte greu (adică programul să fie greșit dar să meargă **aproape** tot timpul); acest lucru face nedeterminist comportamentul programului și dificilă investigarea problemei.
Line 134: Line 141:
  pc_buffer.storage[pc_buffer.size] = ITEM;  pc_buffer.storage[pc_buffer.size] = ITEM;
  pc_buffer.size++;​  pc_buffer.size++;​
 + pthread_cond_signal(&​buffer_empty_cond);​
  printf("​Producer %zu created item.\n",​ idx);  printf("​Producer %zu created item.\n",​ idx);
  pthread_mutex_unlock(&​pc_mutex);​  pthread_mutex_unlock(&​pc_mutex);​
Line 149: Line 157:
  pc_buffer.storage[pc_buffer.size] = NO_ITEM;  pc_buffer.storage[pc_buffer.size] = NO_ITEM;
  pc_buffer.size--;​  pc_buffer.size--;​
 + pthread_cond_signal(&​buffer_full_cond);​
  printf("​Consumer %zu removed item.\n",​ idx);  printf("​Consumer %zu removed item.\n",​ idx);
  pthread_mutex_unlock(&​pc_mutex);​  pthread_mutex_unlock(&​pc_mutex);​
Line 157: Line 166:
 În cele de mai sus, înainte de operația de unlock pe mutex am apelat funcția [[http://​pubs.opengroup.org/​onlinepubs/​7908799/​xsh/​pthread_cond_signal.html|pthread_cond_signal]]. Cu ajutorul acestei funcții, thread-ul producător ce tocmai a produs un element trezește un thread consumator care acum are ce consuma; în mod similar thread-ul consumator care a consumat un element trezește un thread producător care acum are loc unde să producă un element. În cele de mai sus, înainte de operația de unlock pe mutex am apelat funcția [[http://​pubs.opengroup.org/​onlinepubs/​7908799/​xsh/​pthread_cond_signal.html|pthread_cond_signal]]. Cu ajutorul acestei funcții, thread-ul producător ce tocmai a produs un element trezește un thread consumator care acum are ce consuma; în mod similar thread-ul consumator care a consumat un element trezește un thread producător care acum are loc unde să producă un element.
  
-După actualizarea ​programulu, recompilăm folosind ''​make''​ și apoi îl rulăm. Acum programul va funcționa corespunzător fără problema așteptării nedefinite.+După actualizarea ​programului, recompilăm folosind ''​make''​ și apoi îl rulăm. Acum programul va funcționa corespunzător fără problema așteptării nedefinite.
 ==== Granularitate regiune critică ==== ==== Granularitate regiune critică ====
  
Line 171: Line 180:
 </​code>​ </​code>​
  
-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).+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).
  
 <​note>​ <​note>​
 Î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. Î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.
 </​note>​ </​note>​
- 
so/cursuri/curs-09.1397855690.txt.gz · Last modified: 2014/04/19 00:14 by catalin.vasile3004
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