Cerrojos

De Wiki de Sistemas Operativos
Saltar a: navegación, buscar

Ejemplo de implementación

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

int cerrojo = 0;      /* Inicializamos la variable cerrojo. Esto sería sólo válido para
                         hilos, ya que los procesos no comparten espacio de memoria. La variable se inicializa FUERA de los hilos.
                         Del while en adelante, ya es código perteneciente a los hilos en ejecución. */

while(cerrojo == 1);  // Protocolo de               
cerrojo = 1;          // entrada

...                   // Sección crítica

cerrojo = 0;          // Protocolo de salida

Sin embargo, esto es problemático: Supongamos que tenemos únicamente un proceso con dos hilos (Hx y Hy) y el planificador retira el hilo Hx justo antes de ejecutarse la instrucción cerrojo = 1;. El hilo Hy ejecuta su código, entra en la sección crítica (Esto puede ocurrir ya que cerrojo sigue a 0) 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 la secció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.


5.4 Ejercicio de concurrencia de procesos

5.5 Semáforos