En este tema, exploraremos los conceptos de sincronización y exclusión mutua en sistemas operativos. Estos conceptos son fundamentales para la gestión de la concurrencia y la coordinación de múltiples procesos o hilos que acceden a recursos compartidos.
Conceptos Clave
Sincronización
La sincronización se refiere a la coordinación de la ejecución de procesos o hilos para asegurar que accedan a los recursos compartidos de manera ordenada y sin conflictos. Es crucial para evitar condiciones de carrera, donde el resultado de la ejecución depende del orden en que se ejecutan los procesos.
Exclusión Mutua
La exclusión mutua es una propiedad que asegura que solo un proceso o hilo puede acceder a un recurso crítico (como una sección de código o un dato compartido) en un momento dado. Esto previene la interferencia entre procesos y garantiza la integridad de los datos.
Mecanismos de Sincronización y Exclusión Mutua
- Bloqueos (Locks)
Los bloqueos son mecanismos que permiten a los procesos o hilos adquirir y liberar acceso a recursos compartidos. Existen varios tipos de bloqueos:
- Mutex (Mutual Exclusion Lock): Un mutex es un tipo de bloqueo que asegura que solo un hilo puede poseer el bloqueo a la vez.
- Spinlock: Un spinlock es un tipo de mutex que hace que el hilo espere activamente (gire) hasta que el bloqueo esté disponible.
Ejemplo de Mutex en C
#include <pthread.h> #include <stdio.h> pthread_mutex_t lock; void* thread_function(void* arg) { pthread_mutex_lock(&lock); // Sección crítica printf("Thread %d está en la sección crítica\n", *(int*)arg); pthread_mutex_unlock(&lock); return NULL; } int main() { pthread_t threads[2]; int thread_ids[2] = {1, 2}; pthread_mutex_init(&lock, NULL); for (int i = 0; i < 2; i++) { pthread_create(&threads[i], NULL, thread_function, &thread_ids[i]); } for (int i = 0; i < 2; i++) { pthread_join(threads[i], NULL); } pthread_mutex_destroy(&lock); return 0; }
Explicación:
pthread_mutex_init(&lock, NULL);
: Inicializa el mutex.pthread_mutex_lock(&lock);
: Adquiere el mutex antes de entrar en la sección crítica.pthread_mutex_unlock(&lock);
: Libera el mutex después de salir de la sección crítica.pthread_mutex_destroy(&lock);
: Destruye el mutex al final.
- Semáforos
Los semáforos son variables que se utilizan para controlar el acceso a recursos compartidos. Pueden ser contadores (semáforos contadores) o binarios (semáforos binarios).
Ejemplo de Semáforo en C
#include <pthread.h> #include <semaphore.h> #include <stdio.h> sem_t semaphore; void* thread_function(void* arg) { sem_wait(&semaphore); // Sección crítica printf("Thread %d está en la sección crítica\n", *(int*)arg); sem_post(&semaphore); return NULL; } int main() { pthread_t threads[2]; int thread_ids[2] = {1, 2}; sem_init(&semaphore, 0, 1); for (int i = 0; i < 2; i++) { pthread_create(&threads[i], NULL, thread_function, &thread_ids[i]); } for (int i = 0; i < 2; i++) { pthread_join(threads[i], NULL); } sem_destroy(&semaphore); return 0; }
Explicación:
sem_init(&semaphore, 0, 1);
: Inicializa el semáforo con un valor de 1.sem_wait(&semaphore);
: Decrementa el semáforo y espera si su valor es 0.sem_post(&semaphore);
: Incrementa el semáforo.sem_destroy(&semaphore);
: Destruye el semáforo al final.
- Monitores
Los monitores son estructuras de alto nivel que combinan datos y procedimientos para garantizar la exclusión mutua. Los procedimientos dentro de un monitor se ejecutan de manera que solo un proceso puede estar activo en un momento dado.
- Variables de Condición
Las variables de condición se utilizan junto con los monitores para permitir que los hilos esperen hasta que una condición específica sea verdadera.
Ejercicios Prácticos
Ejercicio 1: Implementar un Mutex
Implementa un programa en C que utilice un mutex para proteger una sección crítica donde se incrementa un contador compartido por múltiples hilos.
Solución:
#include <pthread.h> #include <stdio.h> #define NUM_THREADS 5 #define NUM_INCREMENTS 1000 pthread_mutex_t lock; int counter = 0; void* increment_counter(void* arg) { for (int i = 0; i < NUM_INCREMENTS; i++) { pthread_mutex_lock(&lock); counter++; pthread_mutex_unlock(&lock); } return NULL; } int main() { pthread_t threads[NUM_THREADS]; pthread_mutex_init(&lock, NULL); for (int i = 0; i < NUM_THREADS; i++) { pthread_create(&threads[i], NULL, increment_counter, NULL); } for (int i = 0; i < NUM_THREADS; i++) { pthread_join(threads[i], NULL); } printf("Counter final: %d\n", counter); pthread_mutex_destroy(&lock); return 0; }
Ejercicio 2: Implementar un Semáforo
Implementa un programa en C que utilice un semáforo para controlar el acceso a una sección crítica donde se decrementa un contador compartido por múltiples hilos.
Solución:
#include <pthread.h> #include <semaphore.h> #include <stdio.h> #define NUM_THREADS 5 #define NUM_DECREMENTS 1000 sem_t semaphore; int counter = 5000; void* decrement_counter(void* arg) { for (int i = 0; i < NUM_DECREMENTS; i++) { sem_wait(&semaphore); counter--; sem_post(&semaphore); } return NULL; } int main() { pthread_t threads[NUM_THREADS]; sem_init(&semaphore, 0, 1); for (int i = 0; i < NUM_THREADS; i++) { pthread_create(&threads[i], NULL, decrement_counter, NULL); } for (int i = 0; i < NUM_THREADS; i++) { pthread_join(threads[i], NULL); } printf("Counter final: %d\n", counter); sem_destroy(&semaphore); return 0; }
Resumen
En esta sección, hemos cubierto los conceptos de sincronización y exclusión mutua, y hemos explorado varios mecanismos para implementarlos, como mutexes, semáforos, monitores y variables de condición. Estos mecanismos son esenciales para gestionar la concurrencia y asegurar la integridad de los datos en sistemas operativos.
Próximo Tema: Problemas Clásicos de Concurrencia
En el siguiente tema, discutiremos algunos problemas clásicos de concurrencia, como el problema del productor-consumidor y el problema de los filósofos comensales, y cómo se pueden resolver utilizando los mecanismos de sincronización y exclusión mutua que hemos aprendido.
Fundamentos de Sistemas Operativos
Módulo 1: Introducción a los Sistemas Operativos
- Conceptos Básicos de Sistemas Operativos
- Historia y Evolución de los Sistemas Operativos
- Tipos de Sistemas Operativos
- Funciones Principales de un Sistema Operativo
Módulo 2: Gestión de Recursos
Módulo 3: Concurrencia
- Conceptos de Concurrencia
- Hilos y Procesos
- Sincronización y Exclusión Mutua
- Problemas Clásicos de Concurrencia