• Non ci sono risultati.

Sincronizzazione con Java

N/A
N/A
Protected

Academic year: 2021

Condividi "Sincronizzazione con Java"

Copied!
27
0
0

Testo completo

(1)
(2)

Corse critiche e sincronizzazione

• Java implementa un meccanismo simile al monitor per

garantire la sincronizzazione fra thread

• Ogni oggetto ha un lock associato ad esso

– Nelle classi possono essere definiti metodi synchronized synchronized int myMethod()

– Un solo thread alla volta può eseguire un metodo synchronized – Se un oggetto ha più di un metodo sincronizzato, comunque uno

solo può essere attivo

(3)

Sistemi Operativi 20/21 IPC 3

Metodi synchronized

• La chiamata di un metodo sincronizzato richiede il “possesso”

del lock

• Se un thread chiamante non possiede il lock (un altro thread

ne è già in possesso), il thread viene sospeso in attesa del lock

• Il lock è rilasciato quando un thread esce da un metodo

sincronizzato

lock owner

(4)

Metodi synchronized

synchronized void incrementaContatore() { int tmp = contatore + 1; if(tmp>maxContatore) maxContatore = tmp; aspetta(milliAspetta); contatore = tmp; }

void synchronized decrementaContatore() { int tmp = contatore;

aspetta(milliAspetta); contatore = tmp - 1; }

(5)

Sistemi Operativi 20/21 IPC 5

Sincronizzazione

• Un Thread può decidere di non proseguire l’esecuzione

– Può allora volontariamente chiamare il metodo wait all’interno di un metodo sincronizzato

(6)

Il metodo wait()

Quando un thread esegue wait(), si verificano i seguenti

eventi:

1. il thread rilascia il lock 2. il thread viene bloccato

3. il thread è posto in una coda di attesa

4. gli altri thread possono ora competere per il lock

lock

owner

(7)

Sistemi Operativi 20/21 IPC 7

Il metodo notify()

Nel momento in cui una condizione che ha provocato una

attesa si è modificata si può riattivare un singolo thread in attesa tramite notify

Quando un thread richiama notify():

1) viene selezionato un thread arbitrario T fra i thread bloccati 2) T torna fra i thread in attesa del lock

(8)

insert() con wait/notify

public synchronized void insert(Object item) { if(count==BUFFER_SIZE) { try { wait(); } catch(InterruptedException e) {} } ++count; buffer[in] = item; in = (in + 1) % BUFFER_SIZE; if(count==1) notify(); }

(9)

Sistemi Operativi 20/21 IPC 9

Sincronizzazioni multiple

notify() seleziona un thread arbitrario.

Non sempre questo è il comportamento desiderato.

• Java non permette di specificare il thread che si vuole

selezionare

notifyAll() “risveglia” tutti i thread in attesa. In questo modo si permette ai thread stessi di decidere chi deve proseguire.

notifyAll() è una strategia conservativa utile quando più thread sono in attesa

(10)

insert() con wait/notifyAll

public synchronized void insert(Object item { while(count==BUFFER_SIZE) { try { wait(); } catch(InterruptedException e) {} } ++count; buffer[in] = item; in = (in + 1) % BUFFER_SIZE; if(count==1) notifyAll(); }

(11)

Sistemi Operativi 20/21 IPC 11

Confronto Monitor / Java

• Monitor

• Un solo processo può entrare

nel monitor ed eseguire una sua procedura

• Variabili condizione

• wait(variabile_condizione) • signal(var. condizione)

• (Qualunque) oggetto

• Un solo thread alla volta

può eseguire uno dei metodi synchronized

• Una sola implicita (this)this.wait()

(12)

remove() con wait/notify

public synchronized Object remove() { while(count==0) { try { wait(); } catch(InterruptedException e) {} } --count;

Object item = buffer[out];

out = (out + 1) % BUFFER_SIZE;

if(count==BUFFER_SIZE-1) notify(); return item;

(13)

Sistemi Operativi 20/21 IPC 15

Metodo sleep

static void sleep( millisecondi )

Il Thread si sospende (non richiede l’uso del processore) per un certo numero di millisecondi

Nel frattempo possono andare in esecuzione thread a bassa priorità

NB

sleep non restituisce il possesso del lock

sleep è un metodo statico della classe Thread

wait è un metodo della classe Object

public void mysleep(long millis) { if(millis<0) millis = (long)(Math.random()*-millis); try { Thread.sleep(millis); } catch(Exception e) {} }

(14)

Sincronizzazione di blocco

• Si definisce scope di un lock è il tempo fra la sua acquisizione ed il suo rilascio

• Tramite la parola chiave synchronized si possono indicare blocchi di codice piuttosto che un metodo intero

• Ne risulta uno scope generalmente più piccolo rispetto alla

(15)

Sistemi Operativi 20/21 IPC 17

Sincronizzazione di blocco

Object mutexLock = new Object(); public void someMethod() {

nonCriticalSection_1(); synchronized(mutexLock) { criticalSection(); } nonCriticalSection_2(); }

(16)

Sincronizzazione di blocco

public class TestRunnableSync implements Runnable { int count;

public void run() { int tmp;

synchronized (this) { tmp = count++; }

String name = Thread.currentThread().getName(); System.out.println(name + " " + tmp);

}

public static void main(String[] args) {

int n=args.length>0?Integer.parseInt(args[0]):10; Runnable runnable = new TestRunnableSync();

for(int i=0; i<n; i++) {

Thread th = new Thread(runnable); th.start();

} }

(17)

Sistemi Operativi 20/21 IPC 20

TestRunnableSync

TestRunnableSync count

Thread Thread Thread Thread

...

Un solo oggetto Runnable

(18)

Sincronizzazione di blocco

public class TestRunnableSync2 implements Runnable { int count;

public void run() { int tmp;

synchronized (this) { tmp = count++; }

String name = Thread.currentThread().getName(); System.out.println(name + " " + tmp);

}

public static void main(String[] args) {

int n=args.length>0?Integer.parseInt(args[0]):10; for(int i=0; i<n; i++) {

Runnable runnable = new TestRunnableSync(); Thread th = new Thread(runnable);

th.start(); }

(19)

Sistemi Operativi 20/21 IPC 22

TestRunnableSync2

TestRunnableSync

count

Thread Thread Thread Thread

...

N oggetti Runnable N oggetti Thread TestRunnableSync count TestRunnableSync count TestRunnableSync count

...

(20)

La classe Timer

• La classe java.util.Timer permette la schedulazione di processi

nel futuro (attenzione esiste anche la classe javax.swing.Timer dal comportamento parzialmente diverso)

Costruttore: Timer()

void schedule(TimerTask task, long delay, long period)

– Permette di eseguire un task periodico dopo un ritardo specificato – Esistono altri costruttori e altri metodi (si veda

(21)

Sistemi Operativi 20/21 IPC 26

La classe TimerTask

• TimerTask è una classe astratta occorre estenderla e definire il

metodo run (ciò che il task deve fare)

long periodo = 1000; // per esempio un secondo java.util.Timer timer = new java.util.Timer(); timer.schedule(new MyTimerTask(), 0, periodo); public class MyTimerClass extends

java.util.TimerTask { public void run() {

// ciò che devo fare } } dovrebbe richiedere un tempo inferiore a periodo

(22)

Un semplice orologio da riga di comando

import java.util.Date;

public class Clock extends Thread {

public static void main(String[] args) { new Clock().start();

}

public void run() { while(true) { System.out.print(new Date() + "\r"); mysleep(1000); } } }

(23)

Sistemi Operativi 20/21 IPC 28

Un orologio per mezzo di TimerTask

import java.util.*;

public class ClockTimerTask extends TimerTask{ public static void main(String[] args) {

int period=Integer.getInteger("period",1000); int delay = Integer.getInteger("delay", 0);

TimerTask task = new ClockTimerTask();

new Timer().schedule(task, delay, period); }

public void run() {

System.out.print(new Date() + "\r"); }

} Nota: un orologio a livello shell unix

(24)

Il barbiere dormiente

• Soluzione java con Lock e Condition • È possibile definire più condizioni

– wait → await – notify → signal

(25)

Sistemi Operativi 20/21 IPC 30

Soluzione

import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock;

import java.util.concurrent.locks.ReentrantLock;

public class SleepingBarberUsingReentrantLock extends Thread { public static final int CHAIRS = 5;

public int numberOfFreeSeats = CHAIRS; // customers waiting for their hair cut.

public Customers customers = new Customers(); // a ReentrantLock for barber with a condition // to wait if the barber is not available

public Lock barber = new ReentrantLock();

public Condition barberAvailable = barber.newCondition();

// ReentrantLock for chairs so that we can increment the counter safely public Lock accessSeats = new ReentrantLock();

(26)

Soluzione

void customer() {

accessSeats.lock(); // tries to get access to the chairs if (numberOfFreeSeats > 0) { // if there are any free seats System.out.println(getName() + " just sat down.");

numberOfFreeSeats--; // sitting down on a chair

customers.releaseCustomer(); // notify the barber that there is a customer accessSeats.unlock(); // don't need to lock the chairs

barber.lock(); // we have to wait if the barber is busy try { barberAvailable.await(); } catch (InterruptedException e) { } finally { barber.unlock(); } get_haircut(); // cutting...

} else { // there are no free seats

System.out.println("There are no free seats. " + getName() + " has left the barbershop."); accessSeats.unlock(); // release the lock on the seats

} }

(27)

Sistemi Operativi 20/21 IPC 32

Soluzione

void barber() { while (true) { try {

// tries to acquire a customer - if none is available he goes to sleep customers.acquireCustomer();

// at this time he has been awaken

// want to modify the number of available seats accessSeats.lock();

numberOfFreeSeats++; // one chair gets free barber.lock();

try {

barberAvailable.signal(); // the barber is ready to cut

} finally {

barber.unlock(); }

accessSeats.unlock(); cutHair(); // cutting...

} catch (InterruptedException ex) {} }

Riferimenti

Documenti correlati

nell'edificio dopo la costruzione di quest'ultimo per iniziativa di parte dei condomini, non rientra nella proprietà comune di tutti i condomini, ma appartiene in proprietà a quelli

Era infatti considerato un temibile oppositore, simbolo della lotta di liberazione dei neri.. 46 Quale di questi trittici di personaggi visse durante il «secolo

Il secondo momento della lotta cattolica arrivò all’inizio degli anni Novanta, quando alcuni pensatori cattolici, Michael Novak e padre Richard John Neuhaus, proposero il

Le persone fisiche titolari di redditi da locazione di immobili ad uso abitativo che hanno applicato la cedolare secca devono dichiarare i redditi soggetti a cedolare secca nel

Al tempo stesso, l’assenza di accordi tra gli Stati europei (o la stessa Ue) e i Paesi di origine dei migranti irregolari, e la sostanziale incapacità politica ed economica di

Il sistema operativo, quando c’è bisogno di eseguire un nuovo servizio (e quindi di mandare in esecuzione un nuovo processo) decide di mandarlo in esecuzione sul processore che

E’ sempre possibile rendere positivo il coefficiente quadratico.. Infatti, nel caso in cui a &lt; 0 , basterà moltiplicare per -1

Più nel dettaglio, il veicolo aziendale strumentale in uso al dipendente o al collaboratore non è imponibile, in quanto l’utilizzo è esclusivamente lavorativo.. Il veicolo aziendale