IL PROBLEMA DELLA MUTUA ESCLUSIONE METODI synchronized

IL PROBLEMA DELLA
MUTUA ESCLUSIONE
i=0
thread 1
thread 2
class Count {
int i = 0;
void incr() {
i+1 1
i = i + 1;
i -1 -1
}
i=1
void decr() {
i = -1
i = i - 1;
}
}
Il valore finale di i dipende dalla sequenza di esecuzione
METODI synchronized
Il modificatore synchronized prescrive che il
metodo a cui si applica sia eseguito da un solo
thread alla volta:
quando un thread esegue un metodo
synchronized, viene fatto un lock dell’oggetto
cui appartiene il metodo (o, per metodi static,
della classe)
quando il thread termina l’esecuzione
l esecuzione del
metodo, viene fatta una unlock
prima di tale unlock, eventuali altri metodi
synchronized si pongono in attesa
1
ESEMPIO
i=0
thread 1
thread 2
class Count {
int i = 0;
synchronized void incr() {
i+1 1
i = i + 1;
i=1
}
synchronized
y
void decr()
() {
i -1 0
i = i - 1;
i=0
}
}
Il valore finale di i NON dipende dalla sequenza di esecuzione
ESEMPIO
import java.util.Vector;
public class MsgQueue {
Vector queue = new Vector();
public synchronized void send(Object obj) {
queue.addElement(obj);
}
public synchronized Object receive() {
if (queue.size() == 0) return null;
Object obj = queue.firstElement();
queue.removeElementAt(0);
return obj;
}
}
2
ESEMPIO
class ExThread extends Thread {
private static int countDown = 5;
public static void main(String args[]) {
ExThread t1,t2;
t1 = new ExThread("Castore");
t1.start();
t2 = new ExThread("Polluce");
t2.start(); }
public ExThread(String str) {
super(str); }
public void run() {
System.out.println(getName() + ": via!");
while(true) {
System.out.println("Thread " +getName() + "(" + countDown + ")");
if(--countDown == 0) return;
} } }
ESEMPIO
public class TestThread {
public static void main(String args[]) {
ExThread2 t1,t2;
t1 = new ExThread2("Castore"); t1.start();
t2 = new ExThread2("Polluce"); t2.start();
}}
class ExThread2 extends Thread {
static int countDown = 15;
public ExThread2(String str) { super(str);}
synchronized static int dec () {
countDown--;
return countDown; }
public void run() {
int x=0;
System.out.println(getName() + ": via!");
while((x=dec())>=0) {
System.out.println("Thread " +getName() + "(" + (x+1) + ")");
}} }
3
Monitor in java
• Caratteristiche principali dei monitor Java
– ME nell’esecuzione dei metodi synchronized
– non ci sono variabili di condizione
– wait(), notify() simili a sleep() , wakeup()
I monitor e la sincronizzazione
di thread in java
In Java, la sincronizzazione di thread per l’accesso concorrente ad oggetti
condivisi si ottiene utilizzando i seguenti costrutti linguistici:
• metodi synchronized
• i metodi wait() , notify() e notifyAll()
Quando una classe C dichiara alcuni metodi come synchronized essa equivale
ad un monitor. Se l’oggetto o è un’istanza di C, è garantita l’esecuzione in
mutua esclusione (da parte di thread diversi che condividono l’oggetto) di
tutti i metodi synchronized (sullo stesso oggetto o).
L differenze
Le
diff
principali
i i li rispetto
i
tt aii monitor
it sono:
• nella stessa classe possono convivere sia metodi synchronized sia metodi
non synchronized
• i metodi wait() e notify() corrispondono a wait() e signal() ma non sono
associati ad una condition (esiste una sola coda di attesa)
4
wait, notify
Sono metodi della classe Object:
public final void wait();
public final void wait(long millis);
public final void notify();
/* rilascia il lock e si
pone in wait */
/* wait con timeout */
//* rilascia il lock e
sveglia un singolo
thread*/
Monitor e Semafori a confronto
I monitor costituiscono un meccanismo di sincronizzazione
di più alto livello rispetto ai semafori,
semafori tuttavia qualsiasi
problema di sincronizzazione risolto con i semafori può
essere risolto con i monitor e viceversa: lo si dimostra
facendo vedere come si può realizzare un semaforo
attraverso i monitor e viceversa.
5
Realizzazione dei
semafori tramite i monitor
type semaforo = monitor;
var semaforo_positivo:condition;
p
g
var val, sospesi:integer;
procedure entry init(valore_iniziale)
{ val = valore_iniziale; }
procedure entry down()
{ if (val==0)
{sospesi = sospesi+1;
semaforo positivo wait;
semaforo_positivo.wait;
sospesi = sospesi-1;}
else { val = val –1;}
}
procedure entry up()
{
if (sospesi>0) {
semaforo_positivo.signal;}
else
{ val = val +1;}
}
{ /*Inizializzazione */
val = 0; sospesi = 0;
}
Semafori in Java
public class Semaphore {
private int value, sospesi;
public Semaphore (int v) {
value=v; sospesi=0;}
public
bli synchronized
h
i d void
id down
d
() {
if (value==0) {
sospesi++;
try { wait()};
catch (InterruptedExeception e {}
sospesi--;}
else {
value--;; }
}
public synchronized void up () {
if (sospesi>0)
{ notify(); }
else{
value++;}
}
6
Uso dei monitor in java
Soluzione per Produttore/Consumatore in Java (parte 1)
Uso dei monitor in java
Soluzione per Produttore/Consumatore in Java
(parte 2)
7