Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
Upcoming SlideShare
memoriafgua
Next
Download to read offline and view in fullscreen.

Share

Sincronizacion

Download to read offline

sincronizacion

Related Books

Free with a 30 day trial from Scribd

See all

Related Audiobooks

Free with a 30 day trial from Scribd

See all
  • Be the first to like this

Sincronizacion

  1. 1. Sincronización Bajo Nivel Cecilia Hernández 2007-1
  2. 2. Múltiples proceesos/hebras en un sistema Seguro? <ul><li>No . Errores si un proceso/hebra escribe estado que podría escribir/leer otro proceso/hebra </li></ul><ul><ul><li>Resultado: No se puede predecir, normalmente difícil de reproducir </li></ul></ul>nueva previa vi g++ suma h1 h2 h3
  3. 3. Procesos/hebras aislados/no aislados <ul><li>Procesos/hebras aisladas o independientes: Procesos/hebras no comparten datos entre ellos </li></ul><ul><ul><li>Resultados de ejecución de procesos/hebras no se ven afectados por la planificación </li></ul></ul><ul><ul><ul><li>Determinístico : Mismas entradas -> mismos resultados </li></ul></ul></ul><ul><ul><ul><li>Ejemplos Multiplicación de matrices, Web server respondiendo requerimientos para diversos clientes </li></ul></ul></ul><ul><li>Procesos/hebras no aisladas: Comparten estado </li></ul><ul><ul><li>Resultados pueden verse afectados por planifiación </li></ul></ul><ul><ul><ul><li>No determínistico : Mismas entradas -> resultados distintos </li></ul></ul></ul><ul><ul><ul><li>Muy difícil de depurar (encontrar errores) </li></ul></ul></ul>
  4. 4. Por qué compartir? <ul><li>Costo </li></ul><ul><ul><li>Comprar M, amortizar costo permitiendo compartir a N entidades (N>M) </li></ul></ul><ul><ul><ul><li>Ejemplos: Una impresora muchos archivos, un computador con muchos procesos, una carretera con muchos autos </li></ul></ul></ul><ul><li>Información </li></ul><ul><ul><li>Un proceso puede necesitar de los resultados de otros </li></ul></ul><ul><ul><ul><li>Proporciona velocidad: hebras ejecutándose concurrentemente/paralelamente </li></ul></ul></ul><ul><ul><ul><li>Proporciona modularidad: capacidad de compartir estado permite separar tareas y comunicarlas sólo cuando es necesario </li></ul></ul></ul><ul><ul><ul><li>Compartir información y recursos muy importante en sociedad moderna. Impresoras, Telefono, internet, etc) </li></ul></ul></ul>
  5. 5. Ejemplo condición de carrera <ul><li>//variable global </li></ul><ul><li>int suma = 0; </li></ul><ul><li>void *uno(void *p) { </li></ul><ul><li>int *pi = (int *)p; </li></ul><ul><li>for (int i = 0; i < *pi; i++) { </li></ul><ul><li>suma++; </li></ul><ul><li>} </li></ul><ul><li>} </li></ul>tiempo lw $t0, offset($s0) lw $t0, offset($s0) addi $t0, $t0, 1 sw $t0, offset($s0) addi $t0, $t0, 1 sw $t0, offset($s0) hebra1 hebra2
  6. 6. Qué hacer? <ul><li>Nada: Puede estar bien. Si suma pierde actualizaciones no importa. </li></ul><ul><ul><li>En la mayoría de las aplicaciones si importa en algún contexto </li></ul></ul><ul><li>No compartir: duplicar estado </li></ul><ul><ul><li>Tratar de maximizar este criterio </li></ul></ul><ul><ul><li>No siempre posible </li></ul></ul><ul><li>Hay una solución general? Si </li></ul><ul><ul><li>Origen del problema? … Entrelazado en la ejecución de hebras </li></ul></ul><ul><ul><ul><li>Entonces, solución prevenirlo </li></ul></ul></ul>
  7. 7. Atomicidad: controlando condiciones de carrera <ul><li>Unidad atómica : secuencia de instrucciones garantizada en su ejecución atómica, como si fuera sólo una </li></ul><ul><ul><li>Si dos hebras ejecutan la misma unidad atómica al mismo tiemp, una hebra ejecutará la secuencia completa antes que la otra comience </li></ul></ul>tiempo hebra1 hebra2 lw $t0, offset($s0) addi $t0, $t0, 1 sw $t0, offset($s0) lw $t0, offset($s0) addi $t0, $t0, 1 sw $t0, offset($s0)
  8. 8. Requerimientos de Secciones Críticas <ul><li>Exclusión Mutua </li></ul><ul><ul><li>A lo más una hebra/proceso puede estar en la sección crítica </li></ul></ul><ul><li>Progreso </li></ul><ul><ul><li>Si una hebra/proceso no está en sección crítica, entonces hebra/proceso no puede impedir que otra hebra/proceso ingrese a sección crítica </li></ul></ul><ul><li>Espera finita </li></ul><ul><ul><li>Si una hebra/proceso está esperando entrar a la sección crítica, entonces en algún momento debe entrar (no esperar infinitamente) </li></ul></ul><ul><li>Eficiencia </li></ul><ul><ul><li>El overhead de entrar/salir de la sección crítica debe ser pequeño en comparación con el tiempo que toma la sección crítica </li></ul></ul>
  9. 9. Soporte de HW para conseguir atomicidad <ul><li>Idea es prevenir que sólo una hebra a la vez ejecute sección crítica </li></ul><ul><ul><li>Cuál es sección crítica en ejemplo? </li></ul></ul><ul><li>HW podría proporcionar instrucción que permitiera incremento atómico </li></ul><ul><ul><li>Aplicable a nuestro ejemplo, pero no general </li></ul></ul><ul><ul><li>En realidad HW proporciona instrucciones atómicas que permiten construir primitivas atómicas aplicables a cualquier requerimiento </li></ul></ul><ul><li>Solución General: locks (bloqueos) </li></ul><ul><ul><li>Justo antes de entrar a sección crítica hebra obtiene lock y antes de salir lo libera </li></ul></ul>Sección crítica lock unlock
  10. 10. Primitiva de sincronización : Locks <ul><li>Lock: variable compartida con 2 operaciones </li></ul><ul><ul><li>lock : obtiene lock, si está usado espera. </li></ul></ul><ul><ul><li>unlock : libera lock, si hay alguien esperando por el puede obtenerlo </li></ul></ul><ul><li>Cómo se usa? Al identificar sección crítica en código se utiliza lock y unlock al principio y fin de sección </li></ul><ul><ul><li>Nuestro ejemplo usando locks sería </li></ul></ul>lock_t suma_lock=INIT; void *uno(void *p) { int *pi = (int *)p; for (int i = 0; i < *pi; i++) { lock(suma_lock); suma++; unlock(suma_lock); } } Resultado: Sólo una hebra ejecutando suma++ a la vez Acceso mutuamente exclusivo locks referidos como mutex en este contexto Ahora sección crítica es atómica
  11. 11. Implementando locks (1) <ul><li>lock_t L = 1; </li></ul><ul><li>lock( L ){ </li></ul><ul><li>while( L == 0); </li></ul><ul><li>L = 0; </li></ul><ul><li>} </li></ul><ul><li>unlock( L ){ </li></ul><ul><li>L = 1; </li></ul><ul><li>} </li></ul><ul><li>Funciona? </li></ul>
  12. 12. Implementando locks (2) <ul><li>Para sistema con un procesador </li></ul><ul><li>lock( L ){ </li></ul><ul><li>desabilitat_int(); </li></ul><ul><li>while( L == 0); </li></ul><ul><li>L = 0; </li></ul><ul><li>habilita_int(); </li></ul><ul><li>} </li></ul><ul><li>unlock( L ){ </li></ul><ul><li>L = 1; </li></ul><ul><li>} </li></ul><ul><li>Funciona? Qué pasa si lock está tomado? </li></ul>
  13. 13. Implementando locks en multiprocesadores <ul><li>Desabilitando interrupciones en todos los procesadores? </li></ul><ul><ul><li>Muy caro </li></ul></ul><ul><ul><li>HW provee instrucciones que permiten implementar locks sin interferir con las interrupciones </li></ul></ul><ul><ul><li>Instrucciones atómicas proporcionadas por HW </li></ul></ul><ul><ul><ul><li>Test and Set </li></ul></ul></ul><ul><ul><ul><li>Atomic swap (aswap) en Intel instrucción xchg </li></ul></ul></ul><ul><ul><ul><ul><li>http://www.intel.com/cd/ids/developer/asmo-na/eng/dc/threading/333935.htm (implementando locks escalables en Multicores) </li></ul></ul></ul></ul><ul><ul><ul><li>Ambas se utilizan para implementar locks </li></ul></ul></ul>
  14. 14. Instrucción Test and Set <ul><li>int test_and_set(int &target){ </li></ul><ul><li>int rv = target; </li></ul><ul><li>target = 1; </li></ul><ul><li>return rv; </li></ul><ul><li>} </li></ul><ul><li>Atómicamente verifica si la celda de memoria es cero, si es así la setea en 1. Si es 1 no hace nada. Retorna el valor antiguo </li></ul>0 1 target = 0 target = 1 Retorna rv = 0 1 1 target = 1 target = 1 Retorna rv = 1
  15. 15. Implementando locks con TAS (Test and Set) <ul><li>void lock (int &lock) { </li></ul><ul><li>while(test_and_set(lock)); </li></ul><ul><li>} </li></ul><ul><li>void unlock (int &lock){ </li></ul><ul><li>lock = 0; </li></ul><ul><li>} </li></ul>void *uno(void *p) { int *pi = (int *)p; for (int i = 0; i < *pi; i++) { lock(suma_lock); suma++; unlock(suma_lock); } } lock_t suma_lock=INIT; Recorde nuestro ejemplo
  16. 16. Swap atómico (aswap) <ul><li>void aswap(int &a, int &b){ </li></ul><ul><li>int temp = a; </li></ul><ul><li>a = b; </li></ul><ul><li>b = temp; </li></ul><ul><li>} </li></ul><ul><li>Intercambio es atómico </li></ul>0 1 a = 0 B = 1 a = 1 b = 0 0 1
  17. 17. Implementando locks con aswap <ul><li>lock = 0; //global </li></ul><ul><li>void lock (int &lock){ </li></ul><ul><li>int key = 1; </li></ul><ul><li>while(key == 1)aswap(lock, key); </li></ul><ul><li>} </li></ul><ul><li>void unlock (int &lock){ </li></ul><ul><li>lock = 0; </li></ul><ul><li>} </li></ul>lock_t suma_lock=INIT; Recorde nuestro ejemplo void *uno(void *p) { int *pi = (int *)p; for (int i = 0; i < *pi; i++) { lock(suma_lock); suma++; unlock(suma_lock); } } Qué tienen en común ambas Implementaciones?
  18. 18. Múltiples secciones críticas protegida con locks <ul><li>Múltiples hebras en ejecución pueden tener múltiples secciones críticas </li></ul><ul><ul><li>Cada sección crítica debe estar protegida con su propio lock </li></ul></ul><ul><ul><li>Se usan locks para garantizar exclusión mutua </li></ul></ul>SC1 SC2 SC3 P2 P3 P1 P3 P4
  19. 19. Spinlocks <ul><li>Hebras spin (se dan vuelta en loop) hasta que obtienen lock </li></ul><ul><li>Implementaciones previas usando TAS y aswap son de este tipo </li></ul><ul><li>Problemas con spinning? </li></ul><ul><ul><li>Utilizan CPU para verificar estado sin poder progresar en ejecución </li></ul></ul><ul><ul><li>Por qué podría ser bueno? </li></ul></ul><ul><ul><li>Por qué podría se malo? </li></ul></ul><ul><ul><ul><li>Alguna alternativa? </li></ul></ul></ul>
  20. 20. Spinlocks en un procesador <ul><li>Por cuánto tiempo la hebra que espera lock usa CPU? </li></ul><ul><ul><li>Hasta que consigue lock, para ello cada vez que esta en CPU consume su quantum esperando </li></ul></ul><ul><ul><li>Normalmente en este sistema en lugar se spin se bloquea </li></ul></ul><ul><ul><ul><li>Locks implementan colas de espera cuando lock es liberado se entrega lock a la primera hebra en la cola de espera de lock </li></ul></ul></ul>
  21. 21. Spin o bloqueo en multiprocesador <ul><li>Hebras pueden ejecutarse en multiples CPU </li></ul><ul><li>Bloqueo no es gratis </li></ul><ul><ul><li>Requiere cambio de estado (bloquear y resumir) de hebras lo que requiere a SO manejo de sus estructuras de datos </li></ul></ul><ul><li>Decisión debería considerarse cuando se sabe cuanto tiempo se necesita hasta la liberación de lock </li></ul><ul><ul><li>Si se libera pronto Spinlock es mejor </li></ul></ul><ul><ul><li>Si no mejor bloqueo </li></ul></ul><ul><li>Algoritmo </li></ul><ul><ul><li>Spin por el largo del costo del bloqueo </li></ul></ul><ul><ul><li>Si lock no esta disponible, bloqueo </li></ul></ul>tiempo Costo bloqueo spin bloqueo Espera lock Lock liberado por otra hebra Esta hebra obtiene lock Hebra en ejecución
  22. 22. Desempeño <ul><li>Suponga que costo de bloqueo es N ciclos </li></ul><ul><ul><li>Bloquear y resumir hebra </li></ul></ul><ul><li>Si hebra obtiene lock después de M ciclos de espera ocupada (spinning) (M <= N) entonces M es el costo óptimo </li></ul><ul><ul><li>Alternativa de bloqueo inmediato habría sido al costo N, pero spinning conseguimos M (y M <= N) </li></ul></ul><ul><li>Pero caso </li></ul><ul><ul><li>Si hebra espera por N ciclos spinning y luego se bloquea y resume porque lock fue liberado </li></ul></ul><ul><ul><li>costo bloqueo es 2N (un N para spinning y N para bloqueo y resumen de hebra) </li></ul></ul><ul><li>Desempeño siempre dentro de factor de 2 del óptimo </li></ul>
  23. 23. Ejemplo exclusión mutua usando locks mutex pthreads <ul><li>void *uno(void *p) { </li></ul><ul><li>int *pi = (int *)p; </li></ul><ul><li>for (int i = 0; i < *pi; i++) { </li></ul><ul><li>suma++; </li></ul><ul><li>} </li></ul><ul><li>} </li></ul><ul><li>Condición de carrera </li></ul><ul><li>suma++ (3 instrucciones de lenguaje de máquina) </li></ul><ul><li>Sección crítica </li></ul><ul><li>suma++ </li></ul><ul><li>Sincronización </li></ul><ul><li> Usando locks (hacer atómica las tres instrucciones que componen suma++) </li></ul>
  24. 24. Mutex pthreads <ul><li>pthread_mutex_t suma_lock; </li></ul><ul><ul><li>declara mutex </li></ul></ul><ul><li>pthread_mutex_lock(&suma_lock) </li></ul><ul><ul><li>Operación lock sobre variable suma_ lock </li></ul></ul><ul><li>pthread_mutex_unlock(&suma_lock); </li></ul><ul><ul><li>Operación unlock sobre variable suma_lock </li></ul></ul><ul><ul><li>suma_lock = PTHREAD_MUTEX_INITIALIZER; </li></ul></ul>
  25. 25. Ejemplo (1) <ul><li>pthread_mutex_t suma_lock; </li></ul><ul><li>void *uno(void *p) { </li></ul><ul><li>int *pi = (int *)p; </li></ul><ul><li>pthread_mutex_lock(&suma_lock); </li></ul><ul><li>for (int i = 0; i < *pi; i++) { </li></ul><ul><li>suma++; </li></ul><ul><li>} </li></ul><ul><li>pthread_mutex_unlock(&suma_lock); </li></ul><ul><li>} </li></ul><ul><li>main(){ </li></ul><ul><li>suma_lock = PTHREAD_MUTEX_INITIALIZER; </li></ul><ul><li>} </li></ul>
  26. 26. Ejemplo (2) <ul><li>pthread_mutex_t suma_lock; </li></ul><ul><li>void *uno(void *p) { </li></ul><ul><li>int *pi = (int *)p; </li></ul><ul><li>for (int i = 0; i < *pi; i++) { </li></ul><ul><li>pthread_mutex_lock(&suma_lock); </li></ul><ul><li>suma++; </li></ul><ul><li>pthread_mutex_unlock(&suma_lock); </li></ul><ul><li>} </li></ul><ul><li>} </li></ul><ul><li>Main(){ </li></ul><ul><li>suma_lock = PTHREAD_MUTEX_INITIALIZER; </li></ul><ul><li>} </li></ul>
  27. 27. Locks read/write <ul><li>Utilizados por aplicaciones que permiten mayor concurrencia </li></ul><ul><ul><li>El requerimiento de exclusión mutua es para evitar problemas de lectura/escritura </li></ul></ul><ul><ul><ul><li>Hebras que leen y hebras que escriben no pueden inteferir en sus operaciones </li></ul></ul></ul><ul><ul><ul><li>Múltiples hebras pueden estar leyendo simultaneamente </li></ul></ul></ul>SC W0 W1 R0 R1 Múltiples hebras lectoras pueden accesar recurso SC R0 R1 W0 Sólo una hebra de escritura puede accesar recurso
  28. 28. Requerimientos soportados por locks <ul><li>Exclusión Mutua </li></ul><ul><ul><li>A lo más una hebra a la vez está en sección crítica </li></ul></ul><ul><li>Progreso (no deadlock) </li></ul><ul><ul><li>Si hay requerimientos concurrentes debe permitir el progreso de uno. </li></ul></ul><ul><ul><li>No depende del hebras que están fuera de sección crítica </li></ul></ul><ul><li>Espera finita (no starvation) </li></ul><ul><ul><li>Hebra intentando entrar en sección crítica eventualmente tendrá éxito </li></ul></ul><ul><li>NOTA </li></ul><ul><ul><li>Estos requerimientos no necesariamente se cumplen si no se utilizan adecuadamente </li></ul></ul><ul><ul><ul><li>Requerimientos pueden verse afectados si programación de aplicación con hebras no incluyen pares lock/unlock adecuadamente </li></ul></ul></ul>
  29. 29. Resumen <ul><li>Múltiples hebras + compartiendo estado/recursos = condiciones de carrera </li></ul><ul><li>Como solucionarlo? </li></ul><ul><ul><li>Estado privado no necesita sincronización </li></ul></ul><ul><ul><li>Problemas de condición de carrera difíciles de reproducir y descubrir </li></ul></ul><ul><ul><li>Locks es una alternativa de bajo nivel para incorporar sincronización y evitar condiciones de carrera </li></ul></ul><ul><ul><ul><li>Spin locks, bloqueo </li></ul></ul></ul><ul><ul><ul><li>Se requiere hacerlo bien para respetar requerimientos de transparencia anterior </li></ul></ul></ul>
  30. 30. Mecanismos de Sincronización para Secciones Críticas <ul><li>Locks </li></ul><ul><ul><li>Elementales, usados para construir otros </li></ul></ul><ul><li>Semáforos </li></ul><ul><ul><li>Básicos, a veces difíciles de manejar correctamente </li></ul></ul><ul><li>Monitores </li></ul><ul><ul><li>De alto nivel, debe ser soportado por lenguaje de programación </li></ul></ul><ul><ul><li>Fácil de usarlos </li></ul></ul><ul><ul><li>En Java es posible crear monitores con synchronized() </li></ul></ul><ul><li>Mensajes </li></ul><ul><ul><li>Modelo de comunicación y sincronización basado en tx atómica de datos a través de un canal </li></ul></ul>

sincronizacion

Views

Total views

3,503

On Slideshare

0

From embeds

0

Number of embeds

55

Actions

Downloads

104

Shares

0

Comments

0

Likes

0

×