📢 Nuovo Corso Bootstrap Completo disponibile!

Esercizi Multi-Threading in C

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;
}