Introducció
En aquest tema, explorarem els conceptes de sincronització i exclusió mútua en el context de la concurrència en sistemes operatius. La sincronització és crucial per garantir que múltiples fils o processos puguin accedir i modificar recursos compartits sense causar inconsistències. L'exclusió mútua és una tècnica específica per assegurar que només un fil o procés pugui accedir a un recurs crític a la vegada.
Conceptes Clau
Sincronització
La sincronització és el procés de coordinar l'execució de múltiples fils o processos per assegurar que accedeixin als recursos compartits de manera ordenada i segura.
- Condicions de carrera: Situacions on el resultat de l'execució depèn de l'ordre en què s'executen els fils o processos.
- Variables de condició: Utilitzades per bloquejar un fil fins que una condició específica es compleixi.
- Semàfors: Estructures de dades que es poden utilitzar per controlar l'accés a recursos compartits.
Exclusió Mútua
L'exclusió mútua és una tècnica per assegurar que només un fil o procés pugui accedir a una secció crítica del codi a la vegada.
- Secció crítica: Part del codi que accedeix a un recurs compartit.
- Locks (bloquejos): Mecanismes per implementar l'exclusió mútua.
- Mutex (mutual exclusion object): Un tipus específic de lock que assegura que només un fil pugui accedir a la secció crítica a la vegada.
Implementació de Sincronització i Exclusió Mútua
Utilització de Semàfors
Els semàfors són eines poderoses per gestionar la sincronització i l'exclusió mútua. Hi ha dos tipus principals de semàfors:
- Semàfor binari: Pot tenir només dos valors (0 i 1), similar a un mutex.
- Semàfor comptador: Pot tenir un valor més gran que 1, permetent que múltiples fils accedeixin a la secció crítica fins a un cert límit.
Exemple de Semàfor Binari
#include <stdio.h> #include <pthread.h> #include <semaphore.h> sem_t sem; void* thread_function(void* arg) { sem_wait(&sem); // Espera fins que el semàfor estigui disponible printf("Secció crítica\n"); sem_post(&sem); // Allibera el semàfor return NULL; } int main() { pthread_t t1, t2; sem_init(&sem, 0, 1); // Inicialitza el semàfor amb valor 1 pthread_create(&t1, NULL, thread_function, NULL); pthread_create(&t2, NULL, thread_function, NULL); pthread_join(t1, NULL); pthread_join(t2, NULL); sem_destroy(&sem); return 0; }
Utilització de Mutex
Els mutex són una altra eina per implementar l'exclusió mútua. Un mutex permet que només un fil accedeixi a la secció crítica a la vegada.
Exemple de Mutex
#include <stdio.h> #include <pthread.h> pthread_mutex_t mutex; void* thread_function(void* arg) { pthread_mutex_lock(&mutex); // Bloqueja el mutex printf("Secció crítica\n"); pthread_mutex_unlock(&mutex); // Allibera el mutex return NULL; } int main() { pthread_t t1, t2; pthread_mutex_init(&mutex, NULL); // Inicialitza el mutex pthread_create(&t1, NULL, thread_function, NULL); pthread_create(&t2, NULL, thread_function, NULL); pthread_join(t1, NULL); pthread_join(t2, NULL); pthread_mutex_destroy(&mutex); return 0; }
Exercicis Pràctics
Exercici 1: Implementació de Semàfors
Implementa un programa en C que utilitzi semàfors per controlar l'accés a una variable compartida entre tres fils. La variable ha de ser incrementada per cada fil, però només un fil ha de poder accedir-hi a la vegada.
Solució
#include <stdio.h> #include <pthread.h> #include <semaphore.h> sem_t sem; int shared_variable = 0; void* thread_function(void* arg) { sem_wait(&sem); shared_variable++; printf("Variable compartida: %d\n", shared_variable); sem_post(&sem); return NULL; } int main() { pthread_t t1, t2, t3; sem_init(&sem, 0, 1); pthread_create(&t1, NULL, thread_function, NULL); pthread_create(&t2, NULL, thread_function, NULL); pthread_create(&t3, NULL, thread_function, NULL); pthread_join(t1, NULL); pthread_join(t2, NULL); pthread_join(t3, NULL); sem_destroy(&sem); return 0; }
Exercici 2: Implementació de Mutex
Implementa un programa en C que utilitzi un mutex per controlar l'accés a una llista enllaçada compartida entre dos fils. Cada fil ha d'afegir un node a la llista, però només un fil ha de poder accedir-hi a la vegada.
Solució
#include <stdio.h> #include <stdlib.h> #include <pthread.h> typedef struct Node { int data; struct Node* next; } Node; Node* head = NULL; pthread_mutex_t mutex; void* thread_function(void* arg) { Node* new_node = (Node*)malloc(sizeof(Node)); new_node->data = *(int*)arg; new_node->next = NULL; pthread_mutex_lock(&mutex); new_node->next = head; head = new_node; pthread_mutex_unlock(&mutex); return NULL; } void print_list() { Node* current = head; while (current != NULL) { printf("%d -> ", current->data); current = current->next; } printf("NULL\n"); } int main() { pthread_t t1, t2; int data1 = 1, data2 = 2; pthread_mutex_init(&mutex, NULL); pthread_create(&t1, NULL, thread_function, &data1); pthread_create(&t2, NULL, thread_function, &data2); pthread_join(t1, NULL); pthread_join(t2, NULL); print_list(); pthread_mutex_destroy(&mutex); return 0; }
Errors Comuns i Consells
- No inicialitzar el semàfor o mutex: Assegura't d'inicialitzar el semàfor o mutex abans d'utilitzar-lo.
- No alliberar el semàfor o mutex: Sempre allibera el semàfor o mutex després d'accedir a la secció crítica per evitar deadlocks.
- Accés no sincronitzat: Qualsevol accés a recursos compartits ha de ser protegit per semàfors o mutex per evitar condicions de carrera.
Conclusió
En aquesta secció, hem après sobre la importància de la sincronització i l'exclusió mútua en la gestió de la concurrència en sistemes operatius. Hem explorat com utilitzar semàfors i mutex per assegurar que múltiples fils o processos puguin accedir a recursos compartits de manera segura i ordenada. Els exercicis pràctics proporcionats ajuden a reforçar aquests conceptes mitjançant la implementació de solucions reals.
Fonaments de Sistemes Operatius
Mòdul 1: Introducció als Sistemes Operatius
- Conceptes Bàsics de Sistemes Operatius
- Història i Evolució dels Sistemes Operatius
- Tipus de Sistemes Operatius
- Funcions Principals d'un Sistema Operatiu
Mòdul 2: Gestió de Recursos
Mòdul 3: Concurrència
- Conceptes de Concurrència
- Fils i Processos
- Sincronització i Exclusió Mútua
- Problemes Clàssics de Concurrència