Introduzione sul concetto di Sincronizzazione. Sincronizzazione basata su cambio di stato → uso funzione wait() che consente di avere un processo padre che si blocca fino a che il processo figlio non finisce il suo compito ed esce quindi con un segnale, oppure effettua uno stop o ripristino. Ci sono esempi molto commentati all’interno del file wait.c
Questa cosa si può fare anche tutto con i thread con la funzione di libreria phtread_join() che aspetta la fine di un thread specifico.
Quando la computazione dipende dall’ordine di esecuzione dei threads sono in una condizione di → race conditions. Parla di sezione critica. Parla di test-and-set. Vedi magari direttamente le slides per questo discorso, bene o male sono informazioni riconducibili ad HPC.
Costrutto del semaforo inventato da Edsger W. Dijjstra, sua maestà. La leggenda vuole che fosse il compito in classe di fine corso di SO del 1965 presso la Eindhoven University. Il semaforo è un numero intero che può essere incrementato o decrementato atomicamente. Questa variabile può essere gestita da diverse funzioni:
Originariamente si chiamavano P and V, proberen e vehogen, dall’olandese. Nei semafori binari il semaforo è inizializzato ad 1 e succede che quando faccio una wait quello torna a zero. Se qualcuno prova ad accedere il valore diventa -1. In questo modo posso andare a implementare la mutua esclusione perché solamente un thread può ottenere il lock.
Se ho un contatore ho una generalizzazione in cui posso avere diversi lock e li uso per andare a fare coordinamenti logici. Un semaforo binario può andare bene solamente per situazioni molto semplici, mentre quelli a contatore sono un più complessi.
Credo sia possibile andare a configurare il thread come attivo e passivo. Ci sono attributi che possono essere configurati: phtread_mutex_init().
Morale della favola: usa bene i mutex
Questi mutex non sono in grado di definire situazioni logiche, per cui: fai X quando avviene Y. Qui andrebbe usato il semaforo contatore. Esempio del produttore e consumatore: il processo padre crea n-threads consumatori e produttori. Abbiamo un elemento che mi inserisce oggetti all’interno dell’array di elementi che vengono consumati dal consumatore. L’array viene gestito in maniera circolare e ho variabile in e out per andare a prendere la prima e l’ultima posizione non vuota.
Counter mi dice quanti elementi sono presenti all’interno dell’array. Immaginiamo di andare ad usare due semafori contatori. Questi sono inizializzati in un certo modo. Questi rappresentano gli eventi:
Come faccio a fare questo? Il produttore può attendere l’evento array vuoto, perché questo vuol dire che il consumatore ha appena finito di consumare un elemento, il produttore lo produce e lo inserisce in mutua esclusione dell’array (così da non avere conflitti con altri produttori). Una volta fatto ciò segnale l’evento array pieno, in questo modo il consumatore potrebbe attendere l’evento array pieno, di modo che sia sicuro di trovare assolutamente qualcosa e in questo caso prendo un elemento in maniera mutua esclusiva e segnalo che un elemento dell’array sia vuoto. Uno attende produce, inserisce, segnala, attenda, … è una catena essenzialmente. La libreria phtreads non ha supporto per semafori contatori, ma puoi usare semafori generici: posix e system5 (posix più carini da usare). Il semaforo ha un nome associato ad una stringa che può interagire con tutti. Un semaforo senza nome non può andare ad interagire tanti elementi è più vincolato a dove viene definito. Vediti slide 50 in poi per vedere il tutto in maniera più schematica.
[20-03-2023]