Dept. of Computer Science Lab 2: Semafori, Barriere, Variabili atomiche in Java Matteo Camilli [email protected] Laboratorio di Sistemi Operativi a.a. 2015/16 Università degli Studi di Bergamo 1 Esercizi Lab2 • Circular buffer • TODO link 2 Semafori • Oggetti usati per controllare l’accesso ad una risorsa condivisa, in un sistema concorrente • java.util.concurrent.Semaphore • ogni semaforo possiede una coda dei processi in attesa di accedere alla risorsa • ogni semaforo consente di definire il numero iniziale di accessi consentiti prima del rilascio delle risorse • in caso in cui il numero di accessi consentiti sia 1 si parla di semaforo binario • PRIMITIVE • acquire: sospende il processo in esecuzione in caso di risorsa non disponibile e lo inserisce nella coda di attesa del semaforo • release: rilascia la risorsa e riattiva il primo processo della coda di attesa cedendogli la risorsa 3 Esempi • Binary semaphore • https://bitbucket.org/sistemioperativiunibg/lab3-semaphore • Bounded Buffer • https://bitbucket.org/sistemioperativiunibg/lab3-boundedbuffer 4 Barriere • Utility usata per sincronizzare un insieme di thread che devono attendersi l’un l’altro • java.util.concurrent.CyclicBarrier • Un oggetto CyclicBarrier è utile in programmi che coinvolgono un numero fissato di thread concorrenti che devono occasionalmente attendersi. La barriera è chiamata cyclic perché può essere riusata dopo che tutti i thread in attesa sono stati rilasciati • Il metodo await() deve essere richiamato sull’oggetto CyclicBarrier per mettere il thread corrente in attesa. • Una volta che tutti i thread risultano in attesa, vengono rilasciati e l’esecuzione riparte dopo l’invocazione del metodo await() • Quando i thread vengono rilasciati è possibile eseguire in modo automatico una routine di “merge” dei risultati parziali 5 Esempi • Cyclic Barrier • https://bitbucket.org/sistemioperativiunibg/lab3-cyclicbarrier 6 Atomic Variables • Oggetti su cui le operazioni concorrenti sono garantite essere atomiche • java.util.concurrent • AtomicBoolean • AtomicInteger • AtomicIntegerArray • AtomicLong • AtomicLongArray 7 Esercizi • Cocke Machine: • Si implementi un programma Java per risolvere il problema di prelevare lattine di coca-cola da una macchinetta e di rifornirla nel caso in cui rimanga vuota. • Si utilizzi a tale scopo i semafori del package java.util.concurrent come meccanismo di sincronizzazione. • Definire le classi per i thread utenti e rifornitore. Definire, inoltre, la classe CokeMachine contenente le lattine di coca-cola (oggetti condivisi) ed i metodi: • remove(...), eseguito dal generico utente per prelevare una lattina dalla macchinetta • deposit(...), eseguito dal fornitore del servizio per caricare la macchinetta nel caso in cui rimane vuota • Si assume che inizialmente la macchinetta sia piena, e che un utente (a scelta: il primo a trovare la macchinetta vuota o l’utente che preleva l’ultima lattina) segnala al fornitore che la macchinetta è vuota, il quale esegue il rifornimento. 8 Esercizi • Binary Semaphore: Implementare la classe BinarySemaphore che consente di regolarizzare l’accesso in sezione critica di più thread concorrenti utilizzando opportunamente la primitiva synchronized ed i metodi wait/notify. La struttura dati che mantiene i thread in attesa di accesso alla risorsa viene gestita come una coda FIFO (First In First Out), ovvero il primo thread che richiede l’accesso alla risorsa è il primo ad essere servito, poi il secondo, e così via. Suggerimento: potete gestire la coda di thread in attesa con un ArrayDeque<Thread>. • Parallel Sum: Implementare l’esercizio della somma parallela introdotto durante l’esercitazione1 utilizzando come meccanismo di sincronizzazione la classe java.util.concurrent.CyclicBarrier. Dopo che i thread eseguono la somma dei risultati parziali, la routine merge viene lanciata automaticamente dopo che tutti i thread hanno terminato ed esegue il calcolo del risultato finale. 9