Lab 4: Locks, Condition Variables in Java - Matteo Camilli

Dept. of Computer Science
Lab 4: Locks, Condition Variables in Java
Matteo Camilli
[email protected]
Laboratorio di Sistemi Operativi a.a. 2015/16
Università degli Studi di Bergamo
1
Esercizi Lab3
• Coke machine
• https://bitbucket.org/sistemioperativiunibg/lab3-cokemachine
2
Lock
• Un altro modo di garantire la mutua esclusione in Java è l’uso dei Lock
• java.util.concurrent.locks.Lock
interface
3
Lock
• I vantaggi di usare un Lock rispetto ad un metodo synchronized sono:
• PIU’ FLESSIBILITA’:
• L’uso della keyword synchronized forza l’acquisizione/rilascio del lock in un unico
blocco. Quando acquisisco lock multipli, devono essere rilasciati nell’ordine
opposto in cui li ho acquisiti.
• LOCK(A) > LOCK(B) > UNLOCK(B) > UNLOCK(A)
• L’uso dei Lock permette di implementare facilmente un chain locking:
• LOCK(A) > LOCK(B) > UNLOCK(A) > LOCK(C) > UNLOCK(B) > …
• PIU’ FUNZIONALITA’:
• Supporto a Condition Object multipli
• L’effetto è quello di avere wait set multipli
4
Condition Variables
• Conditions (chiamate anche condition variables) forniscono un meccanismo per sospendere
(wait) l’esecuzione di thread fino a che non vengono notificati da altri thread che una qualche
condizione risulta essere verificata.
• Le condition variable sono associate ad un Lock. Non è possibile mettersi in attesa su una
condition variable se non ho prima acquisito il Lock Object a cui è associata.
• Quando un thread si mette in attesa su una condition variable, rilascia in modo atomico il lock e
sospende l’esecuzione.
5
Condition Variables
6
Esempio
• Bounded Buffer
• https://bitbucket.org/sistemioperativiunibg/lab4-boundedbuffer
7
Esercizi
• Coke machine:
• Usando i Lock e le Condition variable del package java.util.concurrent.locks come meccanismo di
sincronizzazione, si realizzi in Java una soluzione al problema di prelevare lattine di coca-cola da una
macchinetta e di rifornirla nel caso in cui rimanga vuota.
• Definire le classi per i thread Utente e il thread Fornitore. Completare, inoltre, lo scheletro della classe
CokeMachine (riportata sotto) 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 bel caso in cui rimane
vuota.
• Si assuma che inizialmente la macchinetta è piena, e che un utente (a scelta: il primo a trovare la
macchinetta vuota o l’utente che preleva l’ultima lattina) può segnalare al fornitore che la macchinetta è
vuota.
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class CokeMachine {
private static final int N = 50; //Capacità della macchinetta
private int count ; //Numero effettivo di lattine presenti nella macchinetta
private final Lock lock = new ReentrantLock(); //Lock per la mutua esclusione
//Condition variables
// .... <COMPLETARE>....
}
}
8
Esercizi
• Toilette:
Un ristorante ha una toilette unica per uomini e donne ed ha una capacità limitata a N persone. Si
assuma che ogni utente della toilette (Man / Woman) sia rappresentato in Java da un thread e che il
bagno (Toilettte) sia un oggetto Java condiviso.
Implementare i thread utenti della toilette e
completare la definizione della classe Toilette riportata di seguito realizzando uno schema di
sincronizzazione con Lock e Condition variable del package java.util.concurrent.locks che garantisca i
seguenti vincoli:
• nella toilette non possono esserci contemporaneamente uomini e donne
• nell'accesso alla toilette, le donne hanno la priorità sugli uomini
• Tali condizioni di sincronizzazione devono riflettersi nel codice della classe Toilette nel modo
seguente. Il thread Woman richiamerà il metodo womanIn() per entrare nel bagno e deve essere
sospeso: se ci sono uomini nel bagno, o se il bagno è pieno. Il thread Man esegue il metodo manIn()
per entrare nel bagno e deve essere sospeso: se ci sono donne nel bagno, o se il bagno è pieno, o se
ci sono donne in attesa, e così via come suggerito nel riquadro per i metodi per uscire dal bagno.
9
Esercizi
• Toilette (scheletro):
public class Toilette {
private static int N; //capacità del bagno
private int womenInside; // numero di donne in toilette
// TODO: .. <DA COMPLETARE>
public Toilette(int n){
this.N = n;
// TODO: <DA COMPLETARE>
}
/**
* Provo ad acquisire il lock sulla risorsa Toilette per uscire.
* Acquisito il lock, aggiorno lo stato del bagno per indicare che ci sarà una donna in meno,
* e poi prima di uscire dal bagno e rilasciare il lock: se ci sono donne che aspettano
* risveglio una donna sospesa, altrimenti se non ci sono più donne risveglio tutti gli uomini.
* **/
public void womanOut() {
// TODO: <DA COMPLETARE>
}
…
10
Esercizi
• Toilette (scheletro segue):
…
/**
* Similmente alla donna, ma prima di uscire controlla: se ci sono donne in attesa di entrare
* e se nel bagno non ci sono uomini, allora risveglio tutte le donne sospese; altrimenti,
* se non ci sono donne che aspettano e ci sono, invece, uomini che aspettano, allora risveglio un uomo.
* **/
public void manOut() {
// TODO: <DA COMPLETARE>
}
/**
* Fintanto che la toilette è piena o ci sono uomini in bagno, il thread donna si sospende
* **/
public void womanIn(){
// TODO: <DA COMPLETARE>
}
/** Fintanto che la toilette è piena o ci sono donne in bagno o ci sono donne in attesa
* di entrare, il thread uomo si sospende
* **/
public void manIn() {
// TODO: <DA COMPLETARE>
}
}
11