Diferencia entre revisiones de «Cerrojos»

De Wiki de Sistemas Operativos
Saltar a: navegación, buscar
(Corregido un pequeño error en la frase.)
(Ejemplo de implementación)
Línea 7: Línea 7:
 
                         hilos, ya que los procesos no comparten espacio de memoria */
 
                         hilos, ya que los procesos no comparten espacio de memoria */
  
while(cerrojo == 0);  // Protocolo de
+
while(cerrojo == 0);  // Protocolo de               ¿Pablo, no sería while (cerrojo != 0)?
 
cerrojo = 0;          // entrada
 
cerrojo = 0;          // entrada
  
Línea 18: Línea 18:
  
 
De esta forma, tenemos a dos hilos ejecutando código de la sección crítica. Para evitar este problema, debemos implementar los protocolos de entrada y salida de forma que se ejecuten en una sola instrucción, con lo cual o el planificador retira el uso del procesador antes de esta instrucción, o sino lo retira después de haberla ejecutado.
 
De esta forma, tenemos a dos hilos ejecutando código de la sección crítica. Para evitar este problema, debemos implementar los protocolos de entrada y salida de forma que se ejecuten en una sola instrucción, con lo cual o el planificador retira el uso del procesador antes de esta instrucción, o sino lo retira después de haberla ejecutado.
 
  
 
= Cerrojos mediante instrucciones atómicas =
 
= Cerrojos mediante instrucciones atómicas =

Revisión del 11:31 10 may 2011

Ejemplo de implementación

El siguiente código sería un posible ejemplo del uso de control de concurrencia mediante cerrojos:

int cerrojo = 1;      /* Inicializamos la variable cerrojo. Esto sería sólo válido para
                         hilos, ya que los procesos no comparten espacio de memoria */

while(cerrojo == 0);  // Protocolo de               ¿Pablo, no sería while (cerrojo != 0)?
cerrojo = 0;          // entrada

...                   // Sección crítica

cerrojo = 1;          // Protocolo de salida

Sin embargo, esto es problemático: Supongamos que tenemos únicamente un proceso con dos hilos (Hx y Hy) y el planificador retire al hilo Hx justo antes de ejecutarse la instrucción cerrojo = 0;. El hilo Hy ejecuta su código, entra en la sección crítica (Esto puede ocurrir ya que cerrojo sigue a 1) y el planificador le retira el uso del procesador dentro de ésta. A continuación, se le vuelve a asignar el procesador a Hx.

De esta forma, tenemos a dos hilos ejecutando código de la sección crítica. Para evitar este problema, debemos implementar los protocolos de entrada y salida de forma que se ejecuten en una sola instrucción, con lo cual o el planificador retira el uso del procesador antes de esta instrucción, o sino lo retira después de haberla ejecutado.

Cerrojos mediante instrucciones atómicas

Podemos implementar cerrojos mediante instrucciones especiales de comprobación y puesta a 0 y 1.

int cerrojo = 0;

void lock() {
    while (__sync_lock_test_and_set(&cerrojo, 1));
}

void unlock() {
    __sync_lock_release(&cerrojo);
}

El método lock comprueba mediante __sync_locktest_and_set(&cerrojo,1) el valor del cerrojo: si es 0, cambia el valor del cerrojo a 1 y devuelve 0, por tanto, se sale del while y entra en sección crítica; si es 1, devuelve 1 y continúa comprobando el valor, por tanto, no entra en situación crítica hasta que cambie el valor del cerrojo.

El método unlock, mediante _sync_lock_release(&cerrojo), cambia el valor del cerrojo a 0.