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:

  1. Semàfor binari: Pot tenir només dos valors (0 i 1), similar a un mutex.
  2. 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.

© Copyright 2024. Tots els drets reservats