La concurrència és un concepte fonamental en els sistemes operatius moderns, ja que permet que múltiples tasques es realitzin simultàniament, millorant així l'eficiència i la utilització dels recursos del sistema. En aquesta secció, explorarem els conceptes bàsics de la concurrència, les seves aplicacions i els desafiaments associats.

  1. Què és la Concurrència?

La concurrència es refereix a la capacitat d'un sistema per gestionar múltiples tasques al mateix temps. Això no significa necessàriament que les tasques s'executin exactament al mateix temps (com en el cas del paral·lelisme), sinó que el sistema pot alternar entre tasques de manera que semblin estar executant-se simultàniament.

1.1. Diferència entre Concurrència i Paral·lelisme

  • Concurrència: Es refereix a la gestió de múltiples tasques que poden estar en progrés al mateix temps. No implica necessàriament que les tasques s'executin simultàniament, sinó que poden estar intercalades.
  • Paral·lelisme: Es refereix a l'execució simultània de múltiples tasques en diferents processadors o nuclis de processament.
Concepte Descripció Exemple
Concurrència Gestió de múltiples tasques al mateix temps, alternant entre elles. Un sistema operatiu que alterna entre processos.
Paral·lelisme Execució simultània de múltiples tasques en diferents processadors. Un sistema amb múltiples nuclis executant diferents fils al mateix temps.

  1. Avantatges de la Concurrència

  • Millor Utilització dels Recursos: Permet que els recursos del sistema (CPU, memòria, etc.) siguin utilitzats de manera més eficient.
  • Major Rendiment: Pot millorar el rendiment global del sistema, especialment en sistemes amb múltiples processadors.
  • Millor Resposta: Pot millorar la resposta del sistema, ja que les tasques poden ser ateses de manera més ràpida.

  1. Desafiaments de la Concurrència

  • Condicions de Cursa: Situacions en què el resultat de l'execució depèn de l'ordre en què s'executen les instruccions.
  • Interbloquejos (Deadlocks): Situacions en què dos o més tasques es bloquegen mútuament esperant recursos que l'altra tasca té.
  • Inanició (Starvation): Situació en què una tasca no rep els recursos necessaris per executar-se perquè altres tasques acaparen els recursos.

  1. Models de Concurrència

4.1. Fils (Threads)

Els fils són unitats d'execució dins d'un procés. Un procés pot tenir múltiples fils que comparteixen el mateix espai d'adreces, però s'executen de manera concurrent.

#include <stdio.h>
#include <pthread.h>

void* print_message(void* ptr) {
    char* message = (char*) ptr;
    printf("%s\n", message);
    return NULL;
}

int main() {
    pthread_t thread1, thread2;
    char* message1 = "Fils en execució";
    char* message2 = "Concurrència en acció";

    pthread_create(&thread1, NULL, print_message, (void*) message1);
    pthread_create(&thread2, NULL, print_message, (void*) message2);

    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);

    return 0;
}

4.2. Processos

Els processos són programes en execució que tenen el seu propi espai d'adreces. La concurrència entre processos es gestiona a través del sistema operatiu.

#include <stdio.h>
#include <unistd.h>

int main() {
    pid_t pid = fork();

    if (pid == 0) {
        // Codi del procés fill
        printf("Procés fill\n");
    } else {
        // Codi del procés pare
        printf("Procés pare\n");
    }

    return 0;
}

  1. Exercicis Pràctics

Exercici 1: Crear i Gestionar Fils

Objectiu: Escriu un programa en C que creï tres fils. Cada fil ha de imprimir un missatge diferent.

Solució:

#include <stdio.h>
#include <pthread.h>

void* print_message(void* ptr) {
    char* message = (char*) ptr;
    printf("%s\n", message);
    return NULL;
}

int main() {
    pthread_t thread1, thread2, thread3;
    char* message1 = "Fil 1 en execució";
    char* message2 = "Fil 2 en execució";
    char* message3 = "Fil 3 en execució";

    pthread_create(&thread1, NULL, print_message, (void*) message1);
    pthread_create(&thread2, NULL, print_message, (void*) message2);
    pthread_create(&thread3, NULL, print_message, (void*) message3);

    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);
    pthread_join(thread3, NULL);

    return 0;
}

Exercici 2: Evitar Condicions de Cursa

Objectiu: Escriu un programa en C que creï dos fils que incrementin una variable global. Utilitza mecanismes de sincronització per evitar condicions de cursa.

Solució:

#include <stdio.h>
#include <pthread.h>

int counter = 0;
pthread_mutex_t lock;

void* increment_counter(void* ptr) {
    for (int i = 0; i < 100000; i++) {
        pthread_mutex_lock(&lock);
        counter++;
        pthread_mutex_unlock(&lock);
    }
    return NULL;
}

int main() {
    pthread_t thread1, thread2;

    pthread_mutex_init(&lock, NULL);

    pthread_create(&thread1, NULL, increment_counter, NULL);
    pthread_create(&thread2, NULL, increment_counter, NULL);

    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);

    pthread_mutex_destroy(&lock);

    printf("Counter: %d\n", counter);
    return 0;
}

Conclusió

En aquesta secció, hem explorat els conceptes bàsics de la concurrència, incloent-hi la diferència entre concurrència i paral·lelisme, els avantatges i desafiaments de la concurrència, i els models de concurrència com els fils i els processos. També hem proporcionat exercicis pràctics per reforçar els conceptes apresos. En la següent secció, aprofundirem en els fils i processos, incloent-hi la seva creació i gestió.

© Copyright 2024. Tots els drets reservats