7a.1 Silberschatz, Galvin y Gagne ©2003 Sistemas Operativos 6ª edición Capítulo 7:...

32
7a.1 Silberschatz, Galvin y Gagne ©2003 istemas Operativos 6ª edición Capítulo 7: Sincronización de Capítulo 7: Sincronización de procesos procesos parte a parte a

Transcript of 7a.1 Silberschatz, Galvin y Gagne ©2003 Sistemas Operativos 6ª edición Capítulo 7:...

Page 1: 7a.1 Silberschatz, Galvin y Gagne ©2003 Sistemas Operativos 6ª edición Capítulo 7: Sincronización de procesos parte a.

7a.1 Silberschatz, Galvin y Gagne ©2003Sistemas Operativos 6ª edición

Capítulo 7: Sincronización de procesosCapítulo 7: Sincronización de procesosparte aparte a

Page 2: 7a.1 Silberschatz, Galvin y Gagne ©2003 Sistemas Operativos 6ª edición Capítulo 7: Sincronización de procesos parte a.

7a.2 Silberschatz, Galvin y Gagne ©2003Sistemas Operativos 6ª edición

Sincronización de procesosSincronización de procesos

Antecedentes.

Problema de la sección crítica.

Page 3: 7a.1 Silberschatz, Galvin y Gagne ©2003 Sistemas Operativos 6ª edición Capítulo 7: Sincronización de procesos parte a.

7a.3 Silberschatz, Galvin y Gagne ©2003Sistemas Operativos 6ª edición

AntecedentesAntecedentes

En un ambiente con procesos concurrentes compartiendo datos pueden ocurrir inconsistencias en tales datos.

Para mantener la consistencia en los datos compartidos, es necesario implementar mecanismos para controlar el acceso a los datos por parte de los procesos concurrentes

Como ejemplo tenemos el caso del buffer limitado implementado en el capítulo 4. Existe un problema de consistencia en la variabe cuenta compartida por los procesos productor y consumidor.

Las técnicas desarrolladas en este capítulo se aplican tanto para procesos como hilos. De ahora en adelante se hará referencia a los hilos.

Page 4: 7a.1 Silberschatz, Galvin y Gagne ©2003 Sistemas Operativos 6ª edición Capítulo 7: Sincronización de procesos parte a.

7a.4 Silberschatz, Galvin y Gagne ©2003Sistemas Operativos 6ª edición

Condición de competenciaCondición de competencia

El hilo Productor contiene en su código lo siguiente:

while ( true ) {

while (cuenta = = TAMAÑO_DEL_BUFFER ) ; // espera

// genera un dato y lo coloca en el buffer

buffer[entra] = dato_del_productor;

entra = (entra + 1) % TAMAÑO_DEL_BUFFER;

cuenta++;

}

Page 5: 7a.1 Silberschatz, Galvin y Gagne ©2003 Sistemas Operativos 6ª edición Capítulo 7: Sincronización de procesos parte a.

7a.5 Silberschatz, Galvin y Gagne ©2003Sistemas Operativos 6ª edición

Condición de competenciaCondición de competencia

El hilo Consumidor incluye en su código lo siguiente:

while (true) {

while (cuenta == 0) ; // espera

datoCosumido = buffer[sale];

sale = (sale + 1) % TAMAÑO_DEL_BUFFER ;

cuenta - -;

}

Page 6: 7a.1 Silberschatz, Galvin y Gagne ©2003 Sistemas Operativos 6ª edición Capítulo 7: Sincronización de procesos parte a.

7a.6 Silberschatz, Galvin y Gagne ©2003Sistemas Operativos 6ª edición

Condición de competenciaCondición de competencia cuenta + + puede ser implementada por un compilador a nivel de

lenguaje de máquina de la siguiente manera: registro1 = cuenta registro1 = registro1 + 1 cuenta = registro1

cuenta - - puede ser implementada de la siguiente manera: registro2 = cuenta registro2 = registro2 - 1 cuenta = registro2

Considere la siguiente secuencia de eventos en el tiempo asumiendo que el valor inicial de cuenta es 5 :

t0: Productor ejecuta registro1 = cuenta {registro1 = 5}t1: Productor ejecuta registro1 = registro1 + 1 {registro1 = 6}

Aquí ocurre tiempo expirado y el Productor abandona el CPU.t2: Consumidor ejecuta registro2 = cuenta {registro2 = 5} t3: Consumidor ejecuta registro2 = registro2 - 1 {registro2 = 4} t4: Consumidor ejecuta cuenta = registro2 {cuenta = 4 }

Aquí ocurre tiempo expirado y el Consumidor abandona el CPU. t5: Productor ejecuta cuenta = registro1 {cuenta = 6}

Page 7: 7a.1 Silberschatz, Galvin y Gagne ©2003 Sistemas Operativos 6ª edición Capítulo 7: Sincronización de procesos parte a.

7a.7 Silberschatz, Galvin y Gagne ©2003Sistemas Operativos 6ª edición

Condición de competenciaCondición de competencia

La variable cuenta inicialmente tiene el valor 5.

El hilo Productor coloca un dato en el buffer e incrementa la variable cuenta lo cual debe dar como resultado 6.

El hilo Consumidor retira un dato del buffer y decrementa la variable cuenta lo cual debe dar como resultado 5.

De acuerdo a la secuencia de eventos mostrados en la lámina anterior, la variable cuenta tiene finalmente el valor incorrecto 6 en lugar del valor correcto 5.

Para evitar esta condición de competencia, es necesario sincronizar los hilo. Solo un hilo debe tener acceso a una variable compartida en todo momento.

Page 8: 7a.1 Silberschatz, Galvin y Gagne ©2003 Sistemas Operativos 6ª edición Capítulo 7: Sincronización de procesos parte a.

7a.8 Silberschatz, Galvin y Gagne ©2003Sistemas Operativos 6ª edición

Problema de la región críticaProblema de la región crítica

Para controlar el acceso a un recurso compartido, se declara la sección de código donde se accede al recurso como región crítica.

La entrada de un hilo a la región crítica debe ser controlada de tal manera que al entrar, ningún otro hilo podrá entrar a su propia región crítica.

La ejecución de secciones críticas por los hilos es mutuamente exclusiva en el tiempo.

El problema de la sección crítica consiste en la implementación de algoritmos de cooperación entre los hilos para cumplir con la exclusión mutua sobre una región crítica.

Page 9: 7a.1 Silberschatz, Galvin y Gagne ©2003 Sistemas Operativos 6ª edición Capítulo 7: Sincronización de procesos parte a.

7a.9 Silberschatz, Galvin y Gagne ©2003Sistemas Operativos 6ª edición

Solución al problema de la región críticaSolución al problema de la región crítica Una solución al problema de la región crítica debe cumplir con

los siguientes requerimientos:

1. Exclusión Mutua – Si el hilo Hi está ejecutando su región crítica, entonces ningún otro hilo puede ejecutar su propia región crítica.

2. Progreso – Si ningún hilo se encuentra ejecutando su región crítica y existen otros hilos que están esperando para ejecutar sus propias regiones críticas, la selección del próximo hilo a ejecutar su propia región crítica no puede ser pospuesta indefinidamente.

3. Espera limitada – Debe existir un límite al número de veces que un hilo puede entrar y salir seguidamente a su región crítica mientras existen otros hilos esperando a entrar a sus propias regiones críticas. Esto evita la inanición de los hilos esperando a entrar a sus propias regiones críticas. Se supone que cada hilo se está ejecutando a una

velocidad diferente de cero. No se pueden hacer suposiciones sobre las velocidades

relativas de los hilos.

Page 10: 7a.1 Silberschatz, Galvin y Gagne ©2003 Sistemas Operativos 6ª edición Capítulo 7: Sincronización de procesos parte a.

7a.10 Silberschatz, Galvin y Gagne ©2003Sistemas Operativos 6ª edición

Soluciones para dos hilosSoluciones para dos hilos

Los dos hilos se representan como, T0 and T1. Son implementadas cuatro soluciones. Todas implementan la clase

abstracta ExclusionMutua:

public abstract class ExclusionMutua { { public static void regionCritica( ) {

try {

Thread.sleep ( ( int ) ( Math.random( ) * TIEMPO ) ;

}

catch( InterruptedException e ) { }

}

Page 11: 7a.1 Silberschatz, Galvin y Gagne ©2003 Sistemas Operativos 6ª edición Capítulo 7: Sincronización de procesos parte a.

7a.11 Silberschatz, Galvin y Gagne ©2003Sistemas Operativos 6ª edición

Soluciones para dos hilosSoluciones para dos hilos

public static void regionNoCritica( ) { try {

Thread.sleep ( ( int ) ( Math.random( ) * TIEMPO ) ;

}

catch( InterruptedException e ) { }

}

public abstract void entraRegionCritica( int t ) ; public asbtract void saleRegionCritica( int t ) ;

public static final int TIEMP = 1000 ;

public static final int TURNO_0 = 0 ;

public static final int TURNO_1 = 1 ;

}

Page 12: 7a.1 Silberschatz, Galvin y Gagne ©2003 Sistemas Operativos 6ª edición Capítulo 7: Sincronización de procesos parte a.

7a.12 Silberschatz, Galvin y Gagne ©2003Sistemas Operativos 6ª edición

Un hiloUn hilo

Clase que implementa a un hilo para la solución de la región crítica:

public class Hilo extends Thread {

public Hilo ( String n, int i, ExclusionMutua s ) {

nombre = n ;

id = i ;

region = s ;

}

public void run ( ) {

while ( true ){

region.entraRegionCritica( id ) ;

System.out.println( nombre + “ está dentro de la región crítica “ );

Page 13: 7a.1 Silberschatz, Galvin y Gagne ©2003 Sistemas Operativos 6ª edición Capítulo 7: Sincronización de procesos parte a.

7a.13 Silberschatz, Galvin y Gagne ©2003Sistemas Operativos 6ª edición

Un hiloUn hilo

ExclusionMutua.regionCritica( ) ;

region.saleRegionCritica( id ) ;

System.out.println( nombre + “ está fuera de la región crítica “ ) ;

ExclusionMutua.regionNoCritica( ) ;

}

}

private String nombre ;

private int id ;

private ExclusionMutua region ;

}

Page 14: 7a.1 Silberschatz, Galvin y Gagne ©2003 Sistemas Operativos 6ª edición Capítulo 7: Sincronización de procesos parte a.

7a.14 Silberschatz, Galvin y Gagne ©2003Sistemas Operativos 6ª edición

Un HiloUn Hilo

El hilo se mantiene dentro de la región crítica por un tiempo aleatorio. Esta acción se implementa al invocar al método ExclusiónMutua.regionCritica( ).

El hilo se mantiene fuera de la región crítica por un tiempo aleatorio. Esta acción se implementa al invocar al método ExclusiónMutua.regionNoCritica( ) .

El hilo entra a la región crítica invocando el método abstracto entraRegionCritica( int t ) de la clase ExclusiónMutua.

El hilo sale de la región crítica invocando al método abstracto saleRegionCritica( int t ) de la clase ExclusiónMutua.

Los diferentes algoritmos para resolver el problema de la región crítica serán implementados mediante los métodos abstractos entraRegionCritica( int t ) y saleRegionCritica( int t ).

Page 15: 7a.1 Silberschatz, Galvin y Gagne ©2003 Sistemas Operativos 6ª edición Capítulo 7: Sincronización de procesos parte a.

7a.15 Silberschatz, Galvin y Gagne ©2003Sistemas Operativos 6ª edición

Prueba de algoritmosPrueba de algoritmos

Para crear los dos hilos y probar cada algoritmo se implementa la clase AlgoritmoPrueba que se muestra a continuación:

public class AlgoritmoPrueba {

public static void main ( String args[ ] ) {

ExclusionMutua alg = new Algoritmo1( ) ;

Hilo primero = new Hilo ( “ Hilo_0 “, 0, alg ) ;

Hilo segundo = new Hilo ( “ Hilo_1 “, 1, alg ) ;

primero.start( ) ;

segundo.start( ) ;

}

}

Page 16: 7a.1 Silberschatz, Galvin y Gagne ©2003 Sistemas Operativos 6ª edición Capítulo 7: Sincronización de procesos parte a.

7a.16 Silberschatz, Galvin y Gagne ©2003Sistemas Operativos 6ª edición

Algoritmo 1Algoritmo 1

Los dos hilos comparten una variable compartida común turno, con un valor inicial 0 o 1. Si turno = 1, entonces el hilo T1 puede entrar a la región crítica. Si turno = 0, entonces el hilo T0 puede entrar a la región crítica.

Al salir T0 de su región crítica, establece el valor de turno en 1 para darle oportunidad de entrar al hilo T1. Al salir T1 de su región crítica, establece el valor de turno en 0 para permitir al hilo T0 entrar a la región crítica.

En el Algoritmo 1, el método yield( ) de la clase Thread es utilizado para que un hilo abandone el CPU voluntariamente.

Page 17: 7a.1 Silberschatz, Galvin y Gagne ©2003 Sistemas Operativos 6ª edición Capítulo 7: Sincronización de procesos parte a.

7a.17 Silberschatz, Galvin y Gagne ©2003Sistemas Operativos 6ª edición

Algoritmo 1Algoritmo 1public class Algoritmo_1 implements ExclusionMutua

{

private volatile int turno;

public Algoritmo_1( ) {

turno = TURNO_0;

}

public void entraRegionCritica(int t) {

while (turno != t)

Thread.yield();

}

public void saleRegionCritica(int t) {

turno = 1 - t;

}

}

Page 18: 7a.1 Silberschatz, Galvin y Gagne ©2003 Sistemas Operativos 6ª edición Capítulo 7: Sincronización de procesos parte a.

7a.18 Silberschatz, Galvin y Gagne ©2003Sistemas Operativos 6ª edición

Algoritmo 1Algoritmo 1

Esta solución asegura que sólo un hilo estará en la región crítica en todo momento. Sin embargo no cumple con el segundo requerimiento Progreso para ser una solución al problema de la región crítica. En efecto, si un hilo entra en la región crítica, al salir establece la variable turno para que el otro hilo pueda entrar a la región crítica. Si el otro hilo no entra a la región crítica y el primer hilo requiere volver a su región crítica, no lo puede lograr. Esto se le denomina el problema de la alternancia.

Page 19: 7a.1 Silberschatz, Galvin y Gagne ©2003 Sistemas Operativos 6ª edición Capítulo 7: Sincronización de procesos parte a.

7a.19 Silberschatz, Galvin y Gagne ©2003Sistemas Operativos 6ª edición

Algoritmo 2Algoritmo 2

Para resolver el problema de alternancia presente con el Algoritmo 1, la variable turno será reemplaza por dos variables boolenas, una para cada hilo indicando si está o no en la región crítica.

Boolean[ ] bandera = new boolean[ 2 ]

Inicialmente tienen el valor false indicando que los hilos están fuera de la región crítica.

Page 20: 7a.1 Silberschatz, Galvin y Gagne ©2003 Sistemas Operativos 6ª edición Capítulo 7: Sincronización de procesos parte a.

7a.20 Silberschatz, Galvin y Gagne ©2003Sistemas Operativos 6ª edición

Algoritmo 2Algoritmo 2

public class Algoritmo_2 extends ExclusionMutua {

public Algoritmo_2( ) {

bandera[ 0 ] = false ;

bandera[ 1 ] = false ;

}

public void entraRegionCritica( int t ) {

int otro ;

otro = 1 – t ;

bandera[ t ] = true ;

// Si el otro hilo está en la región crítica, bandera[otro] es true y

// este hilo no puede entrar a a la región crítica al ceder el CPU.

while ( bandera[ otro ] = = true ) Thread.yield( ) ;

}

Page 21: 7a.1 Silberschatz, Galvin y Gagne ©2003 Sistemas Operativos 6ª edición Capítulo 7: Sincronización de procesos parte a.

7a.21 Silberschatz, Galvin y Gagne ©2003Sistemas Operativos 6ª edición

Algoritmo 2Algoritmo 2

public void saleRegionCritica( int t ) {

// Al salir de la región crítica, el hilo establece su bandera

// en false, lo cual permite al otro hilo entrar en la región

// crítica.

bandera[ t ] = false ;

}

private volatile boolean[ ] bandera = new boolean[ 2 ]

}

Page 22: 7a.1 Silberschatz, Galvin y Gagne ©2003 Sistemas Operativos 6ª edición Capítulo 7: Sincronización de procesos parte a.

7a.22 Silberschatz, Galvin y Gagne ©2003Sistemas Operativos 6ª edición

Algoritmo 2Algoritmo 2

El Algoritmo 2 resolvió el problema de la Alternancia. Un hilo puede entrar y salir de la región crítica sin tener que esperar a que el otro hilo entre en la región crítica.

A primera vista se logra la exclusión mutua sobre la región crítica con la secuencia de instrucciones

bandera[ t ] = true ;

while ( bandera[ otro ] = = true ) Thread.yield( ) ;

Si el otro hilo está en la región crítica, bandera[ otro ] es true y

el hilo que está realizando la verificación no puede entar en la región crítica al ceder el CPU invocando el método Thread.yield( ).

Sin embargo, tomando en cuenta que los hilos se ejecutan de manera concurrente, un examen más exhaustivo es necesario.

Page 23: 7a.1 Silberschatz, Galvin y Gagne ©2003 Sistemas Operativos 6ª edición Capítulo 7: Sincronización de procesos parte a.

7a.23 Silberschatz, Galvin y Gagne ©2003Sistemas Operativos 6ª edición

Algoritmo 2Algoritmo 2 Suponga que Hilo_0 ejecuta el siguiente código,

bandera[ 0 ] = true ; // Aquí indica que intenta entrar a la región

// crítica.

// En este momento ocurre el evento tiempo expirado, Hilo_0

// abandona al CPU, Hilo_1 entra al CPU.

while ( bandera[ 1 ] = = true ) Thread.yield( ) ;

Hilo_1 ejecuta el siguiente código,

bandera[ 1 ] = true ; // Indica que intenta entrar a la región crítica.

// Verifica si bandera[ 0 ] = = true y encuentra que esto es cierto

// porque anteriormente Hilo_0 intento entrar a la región crítica.

// Hilo_1 abandona al CPU. Hilo_0 vuelve al CPU.

while ( bandera[ otro ] = = true ) Thread.yield( ) ;

Page 24: 7a.1 Silberschatz, Galvin y Gagne ©2003 Sistemas Operativos 6ª edición Capítulo 7: Sincronización de procesos parte a.

7a.24 Silberschatz, Galvin y Gagne ©2003Sistemas Operativos 6ª edición

Algoritmo 2Algoritmo 2

Hilo_0 vuelve al CPU y verifica si Hilo_1 se encuentra en la región crítica y encuentra que bandera[ 1 ] es true cediendo el CPU. Lo mismo ocurre con Hilo_0. Esta situación se repite indefinidamente sin que ninguno de los hilos pueda avanzar.

Esto se denomina bloqueo mutuo.

No existiendo ningún hilo en la región crítica, ningún hilo puede entrar en la región crítica. El Algoritmo 2 falló.

Page 25: 7a.1 Silberschatz, Galvin y Gagne ©2003 Sistemas Operativos 6ª edición Capítulo 7: Sincronización de procesos parte a.

7a.25 Silberschatz, Galvin y Gagne ©2003Sistemas Operativos 6ª edición

Algoritmo 3Algoritmo 3

Para que no pueda ocurrir el bloqueo mutuo del Algoritmo 2, el establecimiento de la bandera se lleva a cabo después de la verificación de bandera[ otro ].

Page 26: 7a.1 Silberschatz, Galvin y Gagne ©2003 Sistemas Operativos 6ª edición Capítulo 7: Sincronización de procesos parte a.

7a.26 Silberschatz, Galvin y Gagne ©2003Sistemas Operativos 6ª edición

Algoritmo 3Algoritmo 3public class Algoritmo_2 extends ExclusionMutua {

public Algoritmo_2( ) {

bandera[ 0 ] = false ;

bandera[ 1 ] = false ;

}

public void entraRegionCritica( int t ) {

int otro ;

otro = 1 – t ;

while ( bandera[ otro ] = = true ) Thread.yield( ) ;

bandera[ t ] = true ;

}

public void saleRegionCritica( int t ) {

bandera[ t ] = false ;

}

private volatile boolean[ ] bandera = new boolean[ 2 ]

}

Page 27: 7a.1 Silberschatz, Galvin y Gagne ©2003 Sistemas Operativos 6ª edición Capítulo 7: Sincronización de procesos parte a.

7a.27 Silberschatz, Galvin y Gagne ©2003Sistemas Operativos 6ª edición

Algoritmo 3Algoritmo 3

Con el Algoritmo 3 no ocurre la alternancia ni el bloqueo muto. Sin embargo, nuevamente tenemos que realizar un análisis más detallado del algoritmo.

Suponga que el Hilo_0 ejecutó las siguientes instrucciones,

otro = 1 – t ;

while ( bandera[ 1 ] = = true ) Thread.yield( ) ;

// Hilo_0 encuentra que bandera[ 1 ] es false y continua para

// entrar en la región crítica, sin embargo en este punto ocurre el

// evento tiempo expirado. Hilo_0 abandona el CPU y entra al

// CPU el Hilo_1.

bandera[ 0 ] = true ;

Page 28: 7a.1 Silberschatz, Galvin y Gagne ©2003 Sistemas Operativos 6ª edición Capítulo 7: Sincronización de procesos parte a.

7a.28 Silberschatz, Galvin y Gagne ©2003Sistemas Operativos 6ª edición

Algoritmo 3Algoritmo 3

Hilo_1 entra al CPU y ejecuta las siguientes instrucciones,

otro = 1 – 1 ;

while ( bandera[ 0 ] = = true ) Thread.yield( ) ;

// Hilo_1 encuentra que bandera[ 0 ] es false y entra en la región

// crítica.

bandera[ 1 ] = true ;

// Estando dentro da la región crítica ocurre el evento tiempo

// expirado y sale del CPU para que entre el Hilo_0. Hilo_0 entra al CPU y como se encuentra después del punto de

verificación, entra en la región crítica. Hilo_0 e Hilo_1 se encuentran en la región crítica. Esto no

cumple con el primer requerimiento de Exclusión Mutua. El Algoritmo 3 falló.

Page 29: 7a.1 Silberschatz, Galvin y Gagne ©2003 Sistemas Operativos 6ª edición Capítulo 7: Sincronización de procesos parte a.

7a.29 Silberschatz, Galvin y Gagne ©2003Sistemas Operativos 6ª edición

Algoritmo 4Algoritmo 4

El Algoritmo 4 combina las ideas del Algoritmo 1 y del Algoritmo 2. Son utilizadas las dos variables booleanas bandera y una variable compartida turno para romper el bloqueo mutuo si este ocurre.

Inicialmente las dos variables booleanas bandera son establecidas en false y la variable turno en 0 o 1.

Page 30: 7a.1 Silberschatz, Galvin y Gagne ©2003 Sistemas Operativos 6ª edición Capítulo 7: Sincronización de procesos parte a.

7a.30 Silberschatz, Galvin y Gagne ©2003Sistemas Operativos 6ª edición

Algoritmo 4Algoritmo 4

public class Algoritmo_4 extends ExclusionMutua{

public Algoritmo_4( ) {

bandera[ 0 ] = false ;

bandera[ 1 ] = false ;

turno = turno_0 ;

}

public void entraRegionCritica( int t ) {

int otro ;

otro = 1 – t ;

bandera[ t ] = true ;

turno = otro ;

while ( bandera[ otro ] = = true ) && ( turno = = otro )) Thread.yield( );

}

Page 31: 7a.1 Silberschatz, Galvin y Gagne ©2003 Sistemas Operativos 6ª edición Capítulo 7: Sincronización de procesos parte a.

7a.31 Silberschatz, Galvin y Gagne ©2003Sistemas Operativos 6ª edición

Algoritmo 4Algoritmo 4

public void saleRegionCritica( int t ) {

bandera[ t ] = false ;

}

private volatile int turno ;

private volatile boolean[ ] bandera = new boolean[ 2 ] ;

Al aplicar pruebas exhaustivas a este algoritmo se pude observar que cumple con los tres requerimientos necesarios para resolver el problema de la región crítica.

Page 32: 7a.1 Silberschatz, Galvin y Gagne ©2003 Sistemas Operativos 6ª edición Capítulo 7: Sincronización de procesos parte a.

7a.32 Silberschatz, Galvin y Gagne ©2003Sistemas Operativos 6ª edición

Final del capítulo 7 – parte a.Final del capítulo 7 – parte a.