🚀 Nuova versione beta disponibile! Feedback o problemi? Contattaci

Esercizi Multi-Threading in C

Codegrind Team•Jul 12 2024

Ecco degli esercizi semplici con soluzione per praticare il multi-threading in C.

Esercizio 1: Creazione di un Thread

Creare un thread e stamparne un messaggio.
#include <stdio.h>
#include <pthread.h>

void* stampa_messaggio(void* arg) {
    printf("Ciao dal thread!\n");
    return NULL;
}

int main() {
    pthread_t thread;
    pthread_create(&thread, NULL, stampa_messaggio, NULL);
    pthread_join(thread, NULL);
    return 0;
}

Esercizio 2: Passaggio di Argomenti al Thread

Passare un argomento a un thread e stamparlo.
#include <stdio.h>
#include <pthread.h>

void* stampa_numero(void* arg) {
    int numero = *((int*)arg);
    printf("Numero passato al thread: %d\n", numero);
    return NULL;
}

int main() {
    pthread_t thread;
    int numero = 42;
    pthread_create(&thread, NULL, stampa_numero, &numero);
    pthread_join(thread, NULL);
    return 0;
}

Esercizio 3: Creazione di Più Thread

Creare più thread e stampare un messaggio da ciascuno di essi.
#include <stdio.h>
#include <pthread.h>

#define NUM_THREADS 5

void* stampa_messaggio(void* arg) {
    int thread_id = *((int*)arg);
    printf("Ciao dal thread %d!\n", thread_id);
    return NULL;
}

int main() {
    pthread_t threads[NUM_THREADS];
    int thread_ids[NUM_THREADS];

    for (int i = 0; i < NUM_THREADS; i++) {
        thread_ids[i] = i;
        pthread_create(&threads[i], NULL, stampa_messaggio, &thread_ids[i]);
    }

    for (int i = 0; i < NUM_THREADS; i++) {
        pthread_join(threads[i], NULL);
    }

    return 0;
}

Esercizio 4: Utilizzo di Mutex per Sincronizzare l’Accesso a una Variabile Condivisa

Utilizzare un mutex per sincronizzare l'accesso a una variabile condivisa tra due thread.
#include <stdio.h>
#include <pthread.h>

int variabile_condivisa = 0;
pthread_mutex_t mutex;

void* incrementa(void* arg) {
    pthread_mutex_lock(&mutex);
    for (int i = 0; i < 100000; i++) {
        variabile_condivisa++;
    }
    pthread_mutex_unlock(&mutex);
    return NULL;
}

int main() {
    pthread_t thread1, thread2;

    pthread_mutex_init(&mutex, NULL);

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

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

    pthread_mutex_destroy(&mutex);

    printf("Valore finale della variabile condivisa: %d\n", variabile_condivisa);
    return 0;
}

Esercizio 5: Utilizzo di Condition Variable

Utilizzare una condition variable per sincronizzare due thread.
#include <stdio.h>
#include <pthread.h>

pthread_mutex_t mutex;
pthread_cond_t cond;
int pronto = 0;

void* produttore(void* arg) {
    pthread_mutex_lock(&mutex);
    pronto = 1;
    printf("Produttore: dato pronto\n");
    pthread_cond_signal(&cond);
    pthread_mutex_unlock(&mutex);
    return NULL;
}

void* consumatore(void* arg) {
    pthread_mutex_lock(&mutex);
    while (!pronto) {
        pthread_cond_wait(&cond, &mutex);
    }
    printf("Consumatore: dato ricevuto\n");
    pthread_mutex_unlock(&mutex);
    return NULL;
}

int main() {
    pthread_t thread1, thread2;

    pthread_mutex_init(&mutex, NULL);
    pthread_cond_init(&cond, NULL);

    pthread_create(&thread1, NULL, produttore, NULL);
    pthread_create(&thread2, NULL, consumatore, NULL);

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

    pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&cond);

    return 0;
}

Esercizio 6: Creazione di un Pool di Thread

Creare un semplice pool di thread per eseguire un insieme di lavori.
#include <stdio.h>
#include <pthread.h>

#define NUM_THREADS 3
#define NUM_TASKS 5

void* esegui_lavoro(void* arg) {
    int task_id = *((int*)arg);
    printf("Thread %lu esegue il task %d\n", pthread_self(), task_id);
    return NULL;
}

int main() {
    pthread_t threads[NUM_THREADS];
    int task_ids[NUM_TASKS];

    for (int i = 0; i < NUM_TASKS; i++) {
        task_ids[i] = i;
        pthread_create(&threads[i % NUM_THREADS], NULL, esegui_lavoro, &task_ids[i]);
        pthread_join(threads[i % NUM_THREADS], NULL);
    }

    return 0;
}

Esercizio 7: Utilizzo di Barrier per la Sincronizzazione di Thread

Utilizzare una barrier per sincronizzare l'esecuzione di più thread.
#include <stdio.h>
#include <pthread.h>

#define NUM_THREADS 3

pthread_barrier_t barrier;

void* funzione(void* arg) {
    int thread_id = *((int*)arg);
    printf("Thread %d inizia a lavorare\n", thread_id);
    pthread_barrier_wait(&barrier);
    printf("Thread %d continua a lavorare dopo la barriera\n", thread_id);
    return NULL;
}

int main() {
    pthread_t threads[NUM_THREADS];
    int thread_ids[NUM_THREADS];

    pthread_barrier_init(&barrier, NULL, NUM_THREADS);

    for (int i = 0; i < NUM_THREADS; i++) {
        thread_ids[i] = i;
        pthread_create(&threads[i], NULL, funzione, &thread_ids[i]);
    }

    for (int i = 0; i < NUM_THREADS; i++) {
        pthread_join(threads[i], NULL);
    }

    pthread_barrier_destroy(&barrier);

    return 0;
}