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
