1. Scrivere un programma C che prenda in ingresso - da linea di comando - un numero intero N. Sia 'count' una variabile intera globale inizializzata a 0. Il programma crea N thread: ciascun thread incrementa la variabile condivisa 'count' e stampa il proprio indice seguito dal nuovo valore della variabile. L'indice del thread è così determinato: il primo thread creato ha indice 0, il secondo 1, ..., l'N-esimo ha indice N-1. 2. Scrivere un programma C che prenda come ingresso - da linea di comando - N interi compresi tra 0 e 10. N è una costante, e.g. 5. Il programma crea N thread: a) Ciascun thread va in sospensione per un numero di secondi pari al valore del corrispondente parametro e poi stampa il suo indice. b) Al risveglio ciascun thread stampa un messaggio: "Thread #: Woken up!". c) Dopodiché i thread si sincronizzano, ossia aspettano l'ultimo thread. d) Dopo essersi sincronizzati, ciascun thread stampa un messaggio di chiusura ("Thread #: closing..."). Si implementi il punto c prima con i semafori classici (semafori di sincronizzazione) e poi con le variabili condition. Nota: la funzione sleep(int n) sospende il thread corrente per un numero n di secondi. 3. Problema PRODUTTORE - CONSUMATORE Si consideri un array circolare di caratteri, di dimensione LUN = 20. Definiamo 3 thread che operano concorrentemente sull'array: - il thread 1 (produttore) esegue per LUN volte le seguenti operazioni: a) acquisisce la mutua esclusione sull'array; b) Se l'array non è pieno, aggiunge il carattere '-'; c) rilascia la mutua esclusione; - il thread 2 (produttore) esegue per LUN volte le seguenti operazioni: a) acquisisce la mutua esclusione sull'array; b) Se l'array non è pieno, aggiunge il carattere '+'; c) rilascia la mutua esclusione; - il thread 3 (consumatore) esegue per 2*LUN volte le seguenti operazioni: a) acquisisce la mutua esclusione sull'array; b) Se l'array non è vuoto, estrae un carattere (inserendolo in un buffer locale); c) una volta letti tutti i 2*LUN caratteri, li stampa; d) rilascia la mutua esclusione. 4. Scrivere un programma in C che all'avvio crei 3 thread. I thread 0 e 1 compiono ciascuno le seguenti azioni: - per 20 volte: a) acquisiscono la mutua esclusione su una variabile intera condivisa 'count' (inizializzata a 0); b) incrementano count; c) stampano a video il proprio indice e il nuovo valore di count; d) rilasciano la mutua esclusione. Il thread 2 compie le seguenti azioni: - verifica se count ha valore pari a 5: a) se la condizione è falsa, il thread si sospende; b) se la condizione è vera, stampa il proprio id e il messaggio "Threshold reached", poi termina; c) rilascia la mutua esclusione. Utilizzare le variabili condition.