thread [email protected] alessandro … · simultanee in un programma in c#. ......

25
Il linguaggio C# Thread Tecniche di Programmazione avanzata Corso di Laurea Specialistica in Ingegneria Telematica Università Kore – Enna – A.A. 2008-2009 Alessandro Longheu http://www.diit.unict.it/users/alongheu [email protected] 2 A. Longheu – Tecniche di programmazione avanzata Il threading consente di eseguire elaborazioni simultanee in un programma in C#. Lo spazio dei nomi System.Threading fornisce classi e interfacce che supportano la programmazione multithreading la creazione e l'avvio di nuovi thread, la sincronizzazione di più thread, la sospensione e l'interruzione di thread. Per incorporare il threading nel codice C#, è sufficiente creare una funzione da eseguire all'esterno del thread principale e puntarvi un nuovo oggetto Thread Thread

Upload: dinhkhanh

Post on 27-Jul-2018

214 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Thread alessandro.longheu@diit.unict.it Alessandro … · simultanee in un programma in C#. ... quando il metodo termina ... e task. ThreadWithState tws = new ThreadWithState

Il linguaggio C#

Thread

Tecniche di Programmazione avanzata

Corso di Laurea Specialistica in Ingegneria Telematica

Università

Kore –Enna –

A.A. 2008-2009Alessandro Longheuhttp://w

ww.diit.unict.it/users/alongheu

[email protected]

2

A. Longheu –Tecniche di programmazione avanzata

�Il

threading consente

di eseguire

elaborazioni sim

ultanee in un programma in C#

. �Lo spazio dei nom

i System.Threading

fornisce classi e interfacce

che supportano

la program

mazione

multithreading

�la creazione e l'avvio di nuovi thread,

�la sincronizzazione di più

thread, �la sospensione e l'interruzione di thread.

�Per incorporare il threading nel codice C#

, èsufficiente

creare una funzione da eseguire all'esterno del thread principale e puntarvi un nuovo oggetto Thread

Thread

Page 2: Thread alessandro.longheu@diit.unict.it Alessandro … · simultanee in un programma in C#. ... quando il metodo termina ... e task. ThreadWithState tws = new ThreadWithState

3

A. Longheu –Tecniche di programmazione avanzata

Gestione delle risorse

�La strategia più

diffusa consiste nell'utilizzare i thread di lavoro per eseguire attività

lunghe o in cui il tempo

riveste importanza m

a che non richiedono molte delle

risorse utilizzate da altri thread. �lo spazio dei nom

i System.Threading fornisce le classi

per la sincronizzazione dei thread. �Mutex,

�Monitor,

�Interlocked,

�AutoR

esetEvent e ManualR

esetEvent.

4

A. Longheu –Tecniche di programmazione avanzata

Tipi

public sealed class Thread {public static Thread CurrentThread { get; }

// metodi statici

public static void Sleep(int milliSeconds) {...}

...public Thread(ThreadStart startMethod) {...}

// creazione dei threadpublic string N

ame { get; set; }

// proprietàpublic ThreadPriority Priority { get; set; }public ThreadState ThreadState { get; }public bool IsAlive { get; }public bool IsBackground { get; set; }...public void Start() {...}

// metodi

public void Suspend() {...}public void Resum

e() {...}public void Join() {...}

// il chiamante aspetta che il thread term

inipublic void Abort() {...}

// emette ThreadAbortException

public void Interrupt() {...}// chiam

ato solo nello stato WaitSleepState

...}public delegate void ThreadStart();

// metodo senza param

etripublic enum

ThreadPriority {Norm

al, AboveNorm

al, BelowNorm

al, Highest, Low

est}public enum

ThreadState {Unstarted, Running, Suspended, Stopped,Aborted, ...}

Page 3: Thread alessandro.longheu@diit.unict.it Alessandro … · simultanee in un programma in C#. ... quando il metodo termina ... e task. ThreadWithState tws = new ThreadWithState

5

A. Longheu –Tecniche di programmazione avanzata

Esempio

using System;

using System.Threading;

class Printer {char ch;int sleepTim

e;public Printer(char c, int t) {ch =

c; sleepTime =

t;}public void Print() {for (int i =

1; i < 100; i+

+) {

Console.Write(ch);

Thread.Sleep(sleepTime);

}}

}

class Test {static void M

ain() {Printer a =

new Printer('.', 10);

Printer b = new

Printer('*', 100);new

Thread(new ThreadStart(a.Print)).Start();

new Thread(new

ThreadStart(b.Print)).Start();}}

�Due thread che stam

pano caratteri6

A. Longheu –Tecniche di programmazione avanzata

Confronto con Java

Il metodo stop è

deprecatoThreadAbortException

può essere catturata, m

a èrilanciata alla fine del

gestore, tranne se èinvocato ResetAbort.

Tutti i blocchi finally sono eseguiti.

Bisogna implem

entare il metodo run

Qualsiasi m

etodo di tipo void senza param

etri può essere un thread

I Thread utente sono una estensione di Thread

Non è

necessario estendere Thread

class MyThread extends Thread {

public void run() {... thread actions

...}}

Thread t = new

MyThread();

void P() {... thread actions

...}Thread t =

new

Thread(newThreadStart(P));

Java

C#

Page 4: Thread alessandro.longheu@diit.unict.it Alessandro … · simultanee in un programma in C#. ... quando il metodo termina ... e task. ThreadWithState tws = new ThreadWithState

7

A. Longheu –Tecniche di programmazione avanzata

Thread

Thread t = new

Thread(new ThreadStart(P));

Console.WriteLine("nam

e={0}, priority=

{1}, state={2}", t.N

ame, t.Priority,

t.ThreadState);t.N

ame =

"Worker"; t.Priority =

ThreadPriority.BelowNorm

al;t.Start();Thread.Sleep(1);Console.W

riteLine("name=

{0}, priority={1}, state=

{2}", t.Nam

e, t.Priority, t.ThreadState);

t.Suspend();Thread.Sleep(1);Console.W

riteLine("state={0}", t.ThreadState);

t.Resume();

Console.WriteLine("state=

{0}", t.ThreadState);t.Abort();Thread.Sleep(1);Console.W

riteLine("state={0}", t.ThreadState);

Outputnam

e=, priority=

Norm

al, state=Unstarted

name=

Worker, priority=

BelowNorm

al, state=Running

state=Suspended

state=Running

state=Stopped

8

A. Longheu –Tecniche di programmazione avanzata

Diagram

ma di stato di un Thread

Running

Unstarted

t.Start

WaitSleepJoin

Thread.Sleepother.JoinWait(obj)

t.Interrupttim

e overother joinedPulse(obj)

SuspendRequested

safepoint reached

Suspended

t.Resume

AbortRequested

t.Abort

Stopped

t.Abort

Exception caught,finally processed

t.Suspendend of

thread method

Page 5: Thread alessandro.longheu@diit.unict.it Alessandro … · simultanee in un programma in C#. ... quando il metodo termina ... e task. ThreadWithState tws = new ThreadWithState

9

A. Longheu –Tecniche di programmazione avanzata

�Creazione di una classe che esegue il lavoro (Executor)

�Im

plementazione di un m

etodo (void Run())

�Istanza di Executor

�Istanza del Thread inizializzato su Executor

�Esecuzione di start()

Thread

10

A. Longheu –Tecniche di programmazione avanzata

�Modificatore v

olatile

�La parola chiave v

olatile

avvisa il compilatore che più

thread accederanno al mem

bro dati�Il com

pilatore non deve ottimizzare questo m

embro.

�Proprietà

isAlive�Metodo Abort()

�Blocca il thread

�Metodo Join()

�Sincronizza con il thread

�Use this m

ethod to ensure a thread has terminated. The

caller will

block indefinitely

if the

thread does

not term

inate.

Thread

Page 6: Thread alessandro.longheu@diit.unict.it Alessandro … · simultanee in un programma in C#. ... quando il metodo termina ... e task. ThreadWithState tws = new ThreadWithState

11

A. Longheu –Tecniche di programmazione avanzata

Joinusing System

;using System

.Threading;

class Test {static void P() {for (int i =

1; i <= 20; i+

+) {

Console.Write('-');

Thread.Sleep(100);}

}static void M

ain() {Thread t =

new Thread(new

ThreadStart(P));Console.W

rite("start");t.Start();t.Join();

// si sincronizza con la fine del threadConsole.W

riteLine("end");}

}Output

start--------------------end

12

A. Longheu –Tecniche di programmazione avanzata

Gestione dell’Abort

�Abort lancia una eccezione, gestibile dallo stesso thread

using System; using System

.Threading;class Test {static void P() {

try {try {

try {while (true) ;

} catch (ThreadAbortException) { Console.WriteLine("--

inner aborted"); }} catch (ThreadAbortException) { Console.W

riteLine("--outer aborted");

}} finally { Console.WriteLine("--

finally"); }}

static void Main(string[] arg) {

Thread t = new

Thread(new ThreadStart(P));

t.Start(); Thread.Sleep(1);t.Abort(); t.Join(); Console.W

riteLine("done");}

}Output--inner aborted

--outer aborted

--finally

done

Page 7: Thread alessandro.longheu@diit.unict.it Alessandro … · simultanee in un programma in C#. ... quando il metodo termina ... e task. ThreadWithState tws = new ThreadWithState

13

A. Longheu –Tecniche di programmazione avanzata

Begin/end Invoke

�BeginInvoke�System

.AsyncCallback èun delegato da chiam

are quando il m

etodo termina

�Object è

disponibile quando il metodo term

ina

�EndInvoke�Blocking

�Polling

�Waiting

�callbacks

14

A. Longheu –Tecniche di programmazione avanzata

Creazione di un thread

�La creazione di un nuovo oggetto T

hreaddeterm

ina la generazione di un nuovo

thread gestito.

La classe

Thread

dispone di

costruttori che

accettano un

delegato ThreadStart

o Param

eterizedThreadStart. Il

delegato esegue

il wrapping del m

etodo richiamato dal nuovo thread

quando viene eseguita una chiamata al m

etodo Start. �Il

metodo

Startrestituisce

immediatam

ente un

valore, spesso

prima

dell'avvio effettivo del nuovo thread. Èpossibile utilizzare le proprietà

ThreadStatee IsAlive

per determinare lo stato del thread, m

a queste proprietà

non dovrebbero mai essere utilizzate per la sincronizzazione.

�È

possibile passare

parametri

ad un

thread: il

delegato ParameterizedThreadStart

offre una tecnica semplice per passare un

oggetto contenente dati a un thread quando viene chiamato l'overload del

metodo

System.Threading.Thread.Start(System

.Object).

Un'alternativa

(modo 2) consiste nell'incapsulare la routine del thread e i dati in una

classe di supporto e nell'utilizzare il delegato ThreadStart.

�Nessuno di questi delegati restituisce un valore perché

non èpossibile

definire una

posizione per

la restituzione

dei dati

da una

chiamata

asincrona. Per recuperare i risultati di un metodo di thread, è

possibile utilizzare un m

etodo di callback

Page 8: Thread alessandro.longheu@diit.unict.it Alessandro … · simultanee in un programma in C#. ... quando il metodo termina ... e task. ThreadWithState tws = new ThreadWithState

15

A. Longheu –Tecniche di programmazione avanzata

�Esem

pio di passaggio parametri ad un thread tramite modo 1:

using System; using System

.Threading;public class W

ork{ public static void M

ain(){Thread new

Thread =

new Thread(new

ParameterizedThreadStart(W

ork.DoW

ork)); // U

se the overload of the Start method w

ith an Object param

eter new

Thread.Start(42);Work w

= new

Work();

newThread =

new Thread(new

ParameterizedThreadStart(w

.DoM

oreWork));

newThread.Start("The answ

er."); }public static void D

oWork(object data) {

Console.WriteLine("Static thread procedure. D

ata='{0}'", data);

}public void D

oMoreW

ork(object data) {Console.W

riteLine("Instance thread procedure. Data=

'{0}'", data); }}�Questa tecnica non è

tuttavia indipendente dai tipi, poichéconsente di passare al

metodo

Thread.Start(O

bject)

qualsiasi oggetto.

Un m

odo più

efficiente per

passare i dati a una routine del thread consiste nell'inserire sia la routine che i cam

pi dati in un oggetto di lavoro (modo 2)

Creazione di un thread

16

A. Longheu –Tecniche di programmazione avanzata

�Esem

pio di passaggio parametri ad un thread tramite modo 2:

using System;

using System.Threading;

public class ThreadWithState {

private string boilerplate; private int value;public ThreadW

ithState(string text, int number)

{ boilerplate = text; value =

number; }

public void ThreadProc() { Console.W

riteLine(boilerplate, value); }} // EN

D support class

public class Example {

public static void Main()

{ // Supply the state information required by the task.

ThreadWithState tw

s = new

ThreadWithState(

"This report displays the number {0}.", 42);

Thread t = new

Thread(new ThreadStart(tw

s.ThreadProc));t.Start();Console.W

riteLine("Main thread does som

e work, then w

aits.");t.Join();Console.W

riteLine("Independent task completed; m

ain thread ends."); }}

Creazione di un thread

Page 9: Thread alessandro.longheu@diit.unict.it Alessandro … · simultanee in un programma in C#. ... quando il metodo termina ... e task. ThreadWithState tws = new ThreadWithState

17

A. Longheu –Tecniche di programmazione avanzata

�Esem

pio di recupero risultati da un thread: nel

costruttore della

classe contenente i dati e il m

etodo di thread viene accettato anche undelegato che

rappresenta il metodo di callback. Al term

ine del thread, si richiama il delegato

using System; using System

.Threading;public class ThreadW

ithState {private string boilerplate;

private int value;// D

elegate used to execute the callback method w

hen the task is complete.

private ExampleCallback callback;

public ThreadWithState(string t, int n, Exam

pleCallback callbackDelegate)

{ boilerplate = t; value =

n; callback = callbackD

elegate; }public void ThreadProc() { Console.W

riteLine(boilerplate, value);if (callback !=

null) callback(1); }}// EN

D support class

public delegate void ExampleCallback(int lineCount);

public class Example { public static void M

ain() { ThreadW

ithState tws =

new ThreadW

ithState("This displays num

ber {0}.", 42,new Exam

pleCallback(ResultCallback));Thread t =

new Thread(new

ThreadStart(tws.ThreadProc));

t.Start(); Console.WriteLine("M

ain thread does some w

ork, then waits.");

t.Join(); Console.WriteLine(“Indep. task com

pleted; main thread ends."); }

public static void ResultCallback(int lineCount) { Console.W

riteLine("Independent task printed {0} lines.",lineCount); }}

Creazione di un thread

18

A. Longheu –Tecniche di programmazione avanzata

Sospensione thread usando metodi di System

.Threading.Thread:�

Il metodo

Sleep, blocca subito il thread corrente per il num

ero di millisecondi

specificato, cedendo il resto della porzione di tempo a un altro

thread. Un thread

non può chiamare Sleep su un altro.

�Èpossibile interrom

pere un thread in attesa chiamando il m

etodo Interrupt sul

thread bloccato per generare un'eccezione ThreadInterruptedException. Il thread dovrebbe

intercettare l'eccezione

ed eseguire

le operazioni

appropriate per

continuare a funzionare. Se il thread ignora l'eccezione, l'ambiente di esecuzione

la intercetta e interrompe il thread.

�Èinoltre possibile sospendere un thread con S

uspend. Q

uando un thread chiama

Suspend su se stesso, la chiamata bloccherà

il thread fino a quando non verràripreso da un altro thread. Q

uando un thread chiama Suspend su un altro, la

chiamata non è

bloccante e provoca la sospensione dell'altro thread. Se si chiama

il metodo R

esume, un altro thread uscirà

dallo stato di sospensione e riprenderàl'esecuzione.

A differenza

di Sleep,

Suspend non

determina

l'interruzione immediata: il CLR

deve attendere che il thread abbia raggiunto un punto sicuro (un punto nell'esecuzione in corrispondenza del quale è

possibile eseguire le operazioni

di Garbage

Collection). Suspend

e Resum

e non

si basano

sulla cooperazione del thread che viene controllato, sono estrem

amente

intrusivi e possono causare alle applicazioni seri problem

i come i deadlock,

che si verificano ad esem

pio se si sospende un thread che contiene una risorsa richiesta da un altro thread. In .N

ET 2.0, Suspende R

esumesono (infine) obsoleti.

Thread

Page 10: Thread alessandro.longheu@diit.unict.it Alessandro … · simultanee in un programma in C#. ... quando il metodo termina ... e task. ThreadWithState tws = new ThreadWithState

19

A. Longheu –Tecniche di programmazione avanzata

�Lo scheduling dei thread viene stabilito dalla priorità.

�I dettagli

dello scheduler

utilizzato per

determinare

l'ordine in

cui i thread

vengono eseguiti varia in base al sistema operativo.

�In alcuni, viene sem

pre pianificata per prima l'esecuzione del thread con la

prioritàpiù

alta, tra quelli di cui èpossibile l'esecuzione. Se più

thread con la stessa priorità

sono tutti disponibili, l'utilitàdi pianificazione scorre in ciclo i

thread a quella priorità, assegnando a ciascuno di essi una porzione di tempo

fissa in cui effettuare l'esecuzione (time slicing).

�Se un thread con una priorità

piùalta è

disponibile, non verranno eseguiti i thread a priorità

piùbassa. Q

uando non sono piùdisponibili thread eseguibili

a una

determinata

priorità, si

passa alla

prioritàpiù

bassa successiva

e pianifica l'esecuzione dei thread che hanno quella priorità.

�Se diventa eseguibile un thread a priorità

piùalta, il thread a priorità

piùbassa viene interrotto e viene nuovam

ente consentita l'esecuzione del primo.

�Nel sistem

a operativo possono inoltre essere regolate dinamicam

ente le prioritàdel thread m

an mano che l'interfaccia utente di un'applicazione viene spostata tra

il primo piano e il background. In altri O

S èpossibile usare altri algoritm

i. �

Per la

gestione dei

thread in

.NET

vs Window

s, consultare

http://msdn.m

icrosoft.com/it-it/library/74169f59(VS.80).aspx

Thread

20

A. Longheu –Tecniche di programmazione avanzata

�In .N

ET Framew

ork èdisponibile una serie di prim

itive di sincronizzazione per

controllare le

interazioni dei

thread ed

evitare situazioni

di race

condition. Queste

primitive

possono essere

suddivise approssim

ativamente in tre

categorie: blocco, segnalazione e operazioni

interlocked. È

importante

tenere presente

che la

sincronizzazione dei

thread èun processo di cooperazione. Se anche un solo thread accede

direttamente

alla risorsa

protetta ignorando

un meccanism

o di

sincronizzazione, quest'ultimo non potrà

produrre alcun effetto. �Blocchi

�La

forma

piùsem

plice di

blocco è

costituita dall'istruzione

lock

che controlla l'accesso a un blocco di codice (sezione critica). L'istruzione lock viene im

plementata tram

ite i metodi Enter

e Exitdella classe M

onitore

utilizza try…catch…

finally per garantire il rilascio del blocco. �

In genere, l'utilizzo dell'istruzione lock per la protezione di piccoli blocchi di codice, che non si estendono m

ai oltre un singolo metodo, rappresenta

la tecnica ottimale per utilizzare la classe M

onitor.

Sincronizzazione dei thread

Page 11: Thread alessandro.longheu@diit.unict.it Alessandro … · simultanee in un programma in C#. ... quando il metodo termina ... e task. ThreadWithState tws = new ThreadWithState

21

A. Longheu –Tecniche di programmazione avanzata

�La

classe Monitor

fornisce funzionalità

aggiuntive che

possono essere utilizzate insieme all'istruzione lock:

�Il m

etodo TryEnterconsente a un thread di cui è

interrotta l'esecuzione,

in attesa

di una

risorsa, di

abbandonare l'attesa dopo che è

trascorso un determinato intervallo.

Restituisce un valore booleano che può essere utilizzato

per rilevare ed evitare potenziali deadlock.�Il

metodo

Wait

viene chiam

ato da

un thread

in una

sezione critica.

Cede il

controllo della

risorsa e

si interrom

pe finchéquest'ultim

a èdisponibile.

�I m

etodi Pulsee PulseAll

consentono a un thread che sta per rilasciare il blocco o per chiam

are Wait di inserire uno

o piùthread nella coda dei thread pronti, affinché

possano acquisire il blocco.

Sincronizzazione dei thread

22

A. Longheu –Tecniche di programmazione avanzata

�Oltre M

onitor, esiste la classe Mutex. D

iversamente dalla

classe Monitor,

un mutex

può essere

locale o

globale. I

mutex globali, noti anche com

e mutex denom

inati, risultano visibili

attraverso il

sistema

operativo e

possono essere

utilizzati per sincronizzare i thread in piùprocessi o dom

ini applicazioni. I m

utex locali derivano da MarshalByR

efObject e

possono essere utilizzati oltre i limiti del dom

inio applicazione. �

Oltre

Monitor

e Mutex,

esistono classi

per il

blocco non

esclusivo: Èspesso utile concedere a un num

ero limitato di

thread l'accesso simultaneo a una risorsa. I

semafori e i

blocchi in lettura/scrittu

ra sono progettati per controllare

questo tipo di accesso alle risorse in pool.

Sincronizzazione dei thread

Page 12: Thread alessandro.longheu@diit.unict.it Alessandro … · simultanee in un programma in C#. ... quando il metodo termina ... e task. ThreadWithState tws = new ThreadWithState

23

A. Longheu –Tecniche di programmazione avanzata

�Segnalazione

�Il m

odo piùsem

plice per attendere un segnale proveniente da un altro thread consiste nell'eseguire una chiam

ata al metodo

Join,

che determina un'interruzione del thread corrente finché

l'altro non viene com

pletato. �Operazioni Interlocked

�Le

operazioni interlocked

sono sem

plici operazioni

atomiche

eseguite su una posizione della mem

oria dai metodi statici della

classe Interlocked. Q

ueste operazioni comprendono addizioni,

incrementi,

decrementi,

scambi,

scambi

condizionali basati

su confronto e operazioni di lettura per valori a 64 bit su piattaform

e a 32 bit. A

nche se nessuna di queste operazioni consiste in un blocco o

in un

segnale, è

possibile utilizzarle

per costruire

blocchi e

segnali. Essendo

native del

sistema

operativo Window

s, le

operazioni interlocked risultano estremam

ente veloci.

Sincronizzazione dei thread

24

A. Longheu –Tecniche di programmazione avanzata

�Sincronizzazione m

ediante lock�La parola chiave lock contrassegna un blocco di istruzioni com

e sezione critica ottenendo il blocco a

esclusione reciproca

per un

determinato

oggetto.Object thisLock =

new Object();

lock (thisLock) {// Sezione critica}

Sincronizzazione dei thread

Page 13: Thread alessandro.longheu@diit.unict.it Alessandro … · simultanee in un programma in C#. ... quando il metodo termina ... e task. ThreadWithState tws = new ThreadWithState

25

A. Longheu –Tecniche di programmazione avanzata

Lock: lock(Variable) Statem

ent

class Account {// this class is a m

onitorlong val =

0;public void D

eposit(long x) {lock (this) { val +

= x; }

// solo 1 thread alla volta}

public void Withdraw

(long x) {lock (this) { val -=

x; }}

}

Lock effettuato su qualsiasi oggetto (!th

is)

object semaphore =

new object();

...lock (semaphore) { ... critical region ... }

C# vs Java: non metodi sincronizzati ma attrib

uti

[MethodIm

pl(MethodIm

plOptions.Synchronized)]

public void Deposit(long x) {...}

Sincronizzazione dei thread

26

A. Longheu –Tecniche di programmazione avanzata

�L'istruzione

lock impedisce

a un

thread di

accedere a una sezione critica del codice, mentre

un altro thread ègià

presente. �Se un altro thread tenta di accedere a un codice bloccato,

attenderà(in

stato di

blocco) finché

l'oggetto non verràrilasciato

�La

parola chiave

lock chiam

a il metodo

Enterall'inizio del blocco e il m

etodo Exitalla fine

Sincronizzazione dei thread

Page 14: Thread alessandro.longheu@diit.unict.it Alessandro … · simultanee in un programma in C#. ... quando il metodo termina ... e task. ThreadWithState tws = new ThreadWithState

27

A. Longheu –Tecniche di programmazione avanzata

�L’istruzione lock(v) è

un modo sem

plice per invocare i metodi

della classe Monitor

Monitor.Enter(v);

try {Statement

} finally {Monitor.Exit(v);

}

�Se un thread è

abortito durante l’esecuzione di una istruzione finally è

eseguito e il monitor è

rilasciato

Sincronizzazione dei thread

28

A. Longheu –Tecniche di programmazione avanzata

Wait &

Pulse

Monitor.W

ait(lockedVar);EQ

UIVALE A

wait() in Java (lockedVar è

this)Monitor.Pulse(lockedVar);

EQUIVALE A

notify() in JavaMonitor.PulseAll(lockedVar); EQ

UIVALE A

notifyAll() in Java

Esempio

Thread AThread B

lock(v) {lock(v) {

......

Monitor.W

ait(v);Monitor.Pulse(v);

......

}}

1.A richiede lock(v) e va avanti (regione critica libera).2.A esegue W

ait, cambia stato in sleep e rilascia il lock lock.

3.B richiede lock(v) e va avanti (regione critica libera)..4.B esegue Pulse and risveglia A

. Se necessarrio avviene un context swicth fra A

e B.5.A richiede il lock che fallisce perchè

B iènella regione critica.

6.B rilascia il lock; A può eseguire.

Page 15: Thread alessandro.longheu@diit.unict.it Alessandro … · simultanee in un programma in C#. ... quando il metodo termina ... e task. ThreadWithState tws = new ThreadWithState

29

A. Longheu –Tecniche di programmazione avanzata

Wait &

Pulse (2)

�Wait(v) and Pulse(v) possono essere chiam

ati solo in una sequenza di istruzioni controllata dal lock(v).

�Dopo l’esecuzione di Pulse(v) e l’attivazione del thread corrente, altri

thread possono richiedere ed ottenere il lock�

Occorre, quindi, verificare la condizione di controllowhile (condition false) M

onitor.Wait(v);

...make condition true;

Monitor.Pulse(v);

�PulseAll(v)

attiva tutti i threads in attesa di v, m

a ad uno solo èperm

esso di continuare

30

A. Longheu –Tecniche di programmazione avanzata

Sincronizzazione di Thread�

Differenza notify vs notifyall:

�you w

ould use notify() rather than notifyAll() only if you know that

exactly oneother thread is w

aiting for the lock. �

It's inefficient to wake 1000 threads and have 999 of them

blockwhile

one executes. Better to just wake one at a tim

e, usually. Though, if the monitor

object must

be made

public, exposed

to unknow

n code,

unknown threads, then you probably need notifyAll(). Because if you

don't control all the code that could possibly wait() on a given

monitor,

you can't guarantee that notify() will get called again.

�How

ever, if you can't control all code that accesses a given monitor,

you're usually vulnerable to other problems too, like deadlock, so m

aybe it is preferrable synchronizing on private m

onitors for this reason. �

Whether you call notify() or notifyAll() is dependant on the state that

you just changed. If you changed the state, in a manner that can

satisfy one w

aiting thread, then you call notify. If you change the state that can satisfy m

ultiple waiting threads --

like releasing a group of semaphores,

or shutting down the system

(special case) --then you call notifyA

ll().

Page 16: Thread alessandro.longheu@diit.unict.it Alessandro … · simultanee in un programma in C#. ... quando il metodo termina ... e task. ThreadWithState tws = new ThreadWithState

31

A. Longheu –Tecniche di programmazione avanzata

Produttore e consumatore

class Buffer {const int size =

4;char[] buf =

new char[size];

int head = 0, tail =

0, n = 0;

public void Put(char ch) {lock(this) {

while (n =

= size) M

onitor.Wait(this);

buf[tail] = ch; tail =

(tail + 1) %

size; n++;

Monitor.PulseAll(this);

}}public char Get() {

lock(this) {while (n =

= 0) M

onitor.Wait(this);

char ch = buf[head]; head =

(head + 1) %

size;n--;Monitor.PulseAll(this);

return ch;}}}

Produttore piùveloce

PutPutPutPutGet

PutGet

...

Produttore piùveloce

PutPutPutPutGet

PutGet

...

Consumatore più

velocePutGet

PutGet

...

Consumatore più

velocePutGet

PutGet

...

32

A. Longheu –Tecniche di programmazione avanzata

critical

regio

n

entra

nce

roo

m

G1

G2

G3 3 G

etth

reads arriv

e

at the em

pty

bu

ffer

all Get

thread

s are wak

ed u

p;

the first o

ne en

ters the critical

regio

n, read

s the d

ata and

leaves;

G1

G2

G3

re-entra

nce ro

om th

ey en

ter the critical reg

ion

on

e after the o

ther an

d g

o to

sleep

becau

se the b

uffer is e

mp

ty

G1

G2

G3

wa

iting

roo

m

a Pu

tth

read arriv

es;

it enters th

e critical regio

n,

dep

osits its d

ata and

calls PulseA

ll

G1

G2

G3

P1

the o

thers en

ter the w

aiting

roo

m ag

ain, b

ecause th

e bu

ffer

is emp

ty ag

ain

G2

G3

Produttore e consumatore

Page 17: Thread alessandro.longheu@diit.unict.it Alessandro … · simultanee in un programma in C#. ... quando il metodo termina ... e task. ThreadWithState tws = new ThreadWithState

33

A. Longheu –Tecniche di programmazione avanzata

�È

possibile usare

un oggetto

Mutex

per condividere

risorse in una applicazione multithread.

�Lo stato di un oggetto M

utex può essere:�signaled, quando nessun thread lo possiede

�non-signaled, altrim

enti�

Solo un thread può acquisire un oggetto Mutex.

�Ad esem

pio due thread possono gestire una risorsa condivisa per m

ezzo dell’oggetto Mutex, chi ne ha il

controllo ha accesso alla risorsa fino a quando non rilascia (esplicitam

ente) l’oggetto

Esempio M

utex

34

A. Longheu –Tecniche di programmazione avanzata

Mutex

�L'utilizzo di lock o m

onitor risulta utile per impedire l'esecuzione sim

ultanea di blocchi di codice sensibili ai thread, m

a questi costrutti non consentono la com

unicazione di un evento tra un thread e l'altro. Per questa funzione sono necessari gli eventi di sincronizzazione, ossia oggetti caratterizzati da uno di due diversi

stati, segnalato

e non

segnalato, che

possono essere

utilizzati per

attivare e sospendere i thread. L'esecuzione di un thread che tenta di attendere un evento già

segnalato continua senza ritardi.�

Due tipi di eventi di sincronizzazione: AutoR

esetEvente M

anualResetEvent. La

differenza èche AutoR

esetEvent passa automaticam

ente dallo stato segnalato allo stato non segnalato ogni volta che attiva un thread. M

anualResetEvent

consente l'attivazione di un numero qualsiasi di thread con lo stato segnalato e

torna allo stato non segnalato solo quando viene chiamato R

eset.�

un evento èun oggetto che può assum

ere 2 stati: signaled e nonsignaled. �

Un evento dispone di un handle che si utilizza con W

aitHandle com

e un mutex.

�Un thread che attende un evento sarà

bloccato finchèun altro thread segnala

l'evento chiamando M

anualResetEvent.Set o AutoR

esetEvent.Set. �

Se si usa ManualR

esetEvent ènecessario usare il suo m

etodo Reset per

riportarlo allo stato nonsignaled. �

Un AutoR

esetEvent riporta automaticam

ente allo stato nonsignaledappena

al thread in attesa ènotificato che l'evento è

diventato signaled

Page 18: Thread alessandro.longheu@diit.unict.it Alessandro … · simultanee in un programma in C#. ... quando il metodo termina ... e task. ThreadWithState tws = new ThreadWithState

35

A. Longheu –Tecniche di programmazione avanzata

Esempio M

utex

using System;

using System.Threading;

public class MutexSam

ple { static M

utex gM1; static M

utex gM2;

const int ITERS = 100;

static AutoResetEvent Event1 = new

AutoResetEvent(false); static AutoResetEvent Event2 =

new AutoResetEvent(false);

static AutoResetEvent Event3 = new

AutoResetEvent(false); static AutoResetEvent Event4 =

new AutoResetEvent(false);

public static void Main(String[] args) {

gM1 =

new Mutex(true,"M

yMutex");

gM2 =

new Mutex(true);

AutoResetEvent[] evs = new

AutoResetEvent[4]; // Event for t1.

// Associazione degli eventi definiti come AutoResetEvent

evs[0] = Event1; // Event for t1.

evs[1] = Event2; // Event for t2.

evs[2] = Event3; // Event for t3.

evs[3] = Event4; // Event for t4

}

36

A. Longheu –Tecniche di programmazione avanzata

MutexSam

ple tm = new

MutexSam

ple( ); Thread t1 =

new Thread(new

ThreadStart(tm.t1Start));

Thread t2 = new

Thread(new ThreadStart(tm

.t2Start)); Thread t3 =

new Thread(new

ThreadStart(tm.t3Start));

Thread t4 = new

Thread(new ThreadStart(tm

.t4Start));

// Esegue Mutex.W

aitAll(Mutex[] of gM

1 and gM2).

t1.Start( ); // Esegue M

utex.WaitO

ne(Mutex gM

1). t2.Start( ); // Esegue M

utex.WaitAny(M

utex[] of gM1 and gM

2). t3.Start( ); // Esegue M

utex.WaitO

ne(Mutex gM

2). t4.Start( );

Thread.Sleep(2000); Console.WriteLine(" -

Main releases gM

1"); // quando t2 e t3 finiscono inviano il segnalegM

1.ReleaseMutex( );

Thread.Sleep(1000); Console.WriteLine(" -

Main releases gM

2"); // quando t1 e t4 finiscono inviano il segnale gM

2.ReleaseMutex( );

// il programma attende che tutti i thread finiscano.

WaitH

andle.WaitAll(evs);}

Esempio M

utex

Page 19: Thread alessandro.longheu@diit.unict.it Alessandro … · simultanee in un programma in C#. ... quando il metodo termina ... e task. ThreadWithState tws = new ThreadWithState

37

A. Longheu –Tecniche di programmazione avanzata

public void t1Start( ) { Console.W

riteLine("t1Start started, Mutex.W

aitAll(Mutex[])");

Mutex[] gM

s = new

Mutex[2];

gMs[0] =

gM1;

gMs[1] =

gM2;

// Waits until both gM

1 and gM2 are released.

Mutex.W

aitAll(gMs);

Thread.Sleep(2000); Console.W

riteLine("t1Start finished, Mutex.W

aitAll(Mutex[]) satisfied");

gM1.ReleaseM

utex(); gM2.ReleaseM

utex(); // AutoResetEvent.Set() flagging m

ethod is done. Event1.Set( );

}

Esempio M

utex

38

A. Longheu –Tecniche di programmazione avanzata

public void t2Start( ) { Console.W

riteLine("t2Start started"); // attendo per gM

1. gM

1.WaitO

ne( ); gM

1.ReleaseMutex();

// metodo AutoResetEvent.Set()

Event2.Set( ); } public void t3Start( ) {

Mutex[] gM

s = new

Mutex[2];

gMs[0] =

gM1;

gMs[1] =

gM2;

int index = Mutex.W

aitAny(gMs);

gMs[index].ReleaseM

utex(); // AutoResetEvent.Set() Event3.Set( );

} public void t4Start( ) {gM

2.WaitO

ne( ); gM

2.ReleaseMutex();

// AutoResetEvent.Set() Event4.Set( );

}

Esempio M

utex

Page 20: Thread alessandro.longheu@diit.unict.it Alessandro … · simultanee in un programma in C#. ... quando il metodo termina ... e task. ThreadWithState tws = new ThreadWithState

39

A. Longheu –Tecniche di programmazione avanzata

ThreadPool

�In

generale l'utilizzo

della classe

ThreadPoolrappresenta

il modo

piùsem

plice per

gestire più

thread per

attivitàrelativam

ente brevi senza bloccare altri thread.�

ThreadPool Fornisce un pool di thread che può essere utilizzato per inviare elem

enti di lavoro, per elaborare operazioni di I/O

asincrone, per

attendere per

conto di

altri thread

e per

elaborare timer.

�Per

ogni processo

èdisponibile

un pool

di thread,

con dim

ensioni predefinite

pari a

25 thread

per processore

disponibile. �

Il numero di thread nel pool di thread può essere m

odificato utilizzando il m

etodo SetMaxThreads.

�Ciascun thread utilizza le dim

ensioni dello stack predefinite e viene eseguito in base alla priorità

predefinita

40

A. Longheu –Tecniche di programmazione avanzata

ThreadPool

�I pool

di thread

vengono spesso

utilizzati nelle

applicazioni server. Ad ogni richiesta in arrivo viene assegnato un thread del pool. In questo m

odo la richiesta può essere elaborata in modo

asincrono, senza

bloccare il

thread prim

ario o

ritardare l'elaborazione delle richieste successive.

�Una volta com

pletata l'attività, il thread del pool torna in una coda di thread in attesa, dove potrà

essere riutilizzato evitando in questo m

odo la necessitàdi creare un nuovo thread per ogni

attività.�

Esiste in genere un numero m

assimo di thread che è

possibile inserire in un pool. Se tutti i thread sono occupati, le altre attività

vengono inserite in coda finchénon potranno essere

eseguite dai thread che si renderanno disponibili.�

Èpossibile im

plementare un pool di thread personalizzato, m

a risulta più

agevole utilizzare quello fornito con .NET Fram

ework

tramite la classe ThreadPool.

Page 21: Thread alessandro.longheu@diit.unict.it Alessandro … · simultanee in un programma in C#. ... quando il metodo termina ... e task. ThreadWithState tws = new ThreadWithState

41

A. Longheu –Tecniche di programmazione avanzata

�Esistono

diversi scenari

in cui

èpreferibile

creare e

gestire thread

personalizzati anziché

utilizzare quelli

del pool,

in particolare quando: �Ènecessario un thread in prim

o piano.�Ènecessario che un thread abbia una determ

inata priorità.�Sono presenti attività

che bloccano il thread per periodi di tem

po prolungati. Èprevisto un num

ero massim

o di thread del pool e, pertanto, è

possibile che il blocco di numerosi

thread del pool impedisca l'avvio delle attività.

�È

necessario disporre

di un'identità

stabile associata

al thread

oppure utilizzare

un thread

esclusivamente

per un'attività.

ThreadPool

42

A. Longheu –Tecniche di programmazione avanzata

�Il

pool di

thread viene

utilizzato chiam

ando ThreadPool.Q

ueueUserW

orkItem

dal codice

gestito o

CorQueueU

serWorkItem

dal codice non gestito e passando un delegato W

aitCallbackche rappresenta il m

etodo da cui viene eseguita l'attività.

�È

inoltre possibile

accodare elem

enti di

lavoro correlati

a un'operazione

di attesa

utilizzando il

metodo

ThreadPool.RegisterW

aitForSingleObject

e passando un oggetto WaitH

andleche, alla ricezione di un segnale o alla scadenza,

genera una

chiamata

al metodo

rappresentato dal

delegato WaitO

rTimerCallback.

�In

entrambi

i casi,

il pool

di thread

utilizza un

thread in

background per richiamare il m

etodo di callback.

ThreadPool

Page 22: Thread alessandro.longheu@diit.unict.it Alessandro … · simultanee in un programma in C#. ... quando il metodo termina ... e task. ThreadWithState tws = new ThreadWithState

43

A. Longheu –Tecniche di programmazione avanzata

�Esempio ThreadCollection (1):

using System;

using System.Threading;

public class Example {

public static void Main() { // Q

ueue the task.ThreadPool.Q

ueueUserW

orkItem(new

WaitCallback(ThreadProc));

Console.WriteLine("M

ain thread does some w

ork, then sleeps.");// If you com

ment out the Sleep, the m

ain thread exits before// the thread pool task runs. The thread pool uses background// threads, w

hich do not keep the application running. (This// is a sim

ple example of a race condition.)

Thread.Sleep(1000);Console.W

riteLine("Main thread exits."); }

// This thread procedure performs the task.

static void ThreadProc(Object stateInfo) {

// No state object w

as passed to QueueU

serWorkItem

, so // stateInfo is null.Console.W

riteLine("Hello from

the thread pool.");}} ThreadPool

44

A. Longheu –Tecniche di programmazione avanzata

�Esempio ThreadCollection in cui si forniscono dati al pool (2):

using System; using System

.Threading;// TaskInfo holds state inform

ation for a task of a ThreadPool thread.public class TaskInfo {

// State information for the task.

public string Boilerplate; public int Value;public TaskInfo(string text, int num

ber) {Boilerplate =

text; Value = num

ber; }}public class Exam

ple {public static void M

ain() {TaskInfo ti =

new TaskInfo("This report displays the num

ber {0}.", 42);// Q

ueue the task and data.if (ThreadPool.Q

ueueUserW

orkItem(new

WaitCallback(ThreadProc), ti))

{ Console.WriteLine("M

ain thread does some w

ork, then sleeps.");Thread.Sleep(1000);Console.W

riteLine("Main thread exits."); }

else { Console.WriteLine("U

nable to queue ThreadPool request."); } }static void ThreadProc(O

bject stateInfo) {TaskInfo ti =

(TaskInfo) stateInfo;Console.W

riteLine(ti.Boilerplate, ti.Value); }}

ThreadPool

Page 23: Thread alessandro.longheu@diit.unict.it Alessandro … · simultanee in un programma in C#. ... quando il metodo termina ... e task. ThreadWithState tws = new ThreadWithState

45

A. Longheu –Tecniche di programmazione avanzata

The following example demonstrates several threading features (3):

�Queuing

a task

for execution

by ThreadPool

threads, with

the RegisterW

aitForSingleObject

method.

�Signaling a task to execute, w

ith AutoResetEvent.

�Handling both tim

e-outs and signals with a W

aitOrTim

erCallbackdelegate.

�Canceling a queued task w

ith RegisteredW

aitHandle.

using System; using System

.Threading;public class TaskInfo {

public RegisteredWaitH

andle Handle =

null;public string O

therInfo = "default";

}public class Example { public static void M

ain(string[] args){

// The main thread uses AutoResetEvent to signal the registered w

ait handle, // w

hich executes the callback method.

AutoResetEvent ev = new

AutoResetEvent(false);TaskInfo ti =

new TaskInfo(); ti.O

therInfo = "First task";

ThreadPool

46

A. Longheu –Tecniche di programmazione avanzata

The following exam

ple demonstrates several threading features.

…// TaskInfo includes wait handle returned by RegisterW

aitForSingleObject.

// This allows the w

ait ends when the object has been signaled once.

ti.Handle =

ThreadPool.RegisterWaitForSingleO

bject(ev, new

WaitO

rTimerCallback(W

aitProc), ti, 1000, false );// The m

ain thread waits three seconds, to dem

onstrate the// tim

e-outs on the queued thread, and then signals.Thread.Sleep(3100);Console.W

riteLine("Main thread signals.");

ev.Set();// The m

ain thread sleeps, which give the callback tim

e to execute. Thread.Sleep(1000);

// If you start a thread yourself, you can wait for it to end

// by calling Thread.Join. This option is not availablewith thread pool

} ThreadPool

Page 24: Thread alessandro.longheu@diit.unict.it Alessandro … · simultanee in un programma in C#. ... quando il metodo termina ... e task. ThreadWithState tws = new ThreadWithState

47

A. Longheu –Tecniche di programmazione avanzata

The following exam

ple demonstrates several threading features.

…// The callback m

ethod executes when the registered w

ait times out,

// or when the W

aitHandle (in this case AutoResetEvent) is signaled.

// WaitProc unregisters the W

aitHandle the first tim

e the event is signaled.public static void W

aitProc(object state, bool timedO

ut) {// The state object m

ust be cast to the correct type, because the// signature of the W

aitOrTim

erCallback delegate specifies type Object.

TaskInfo ti = (TaskInfo) state;

string cause = "TIM

ED OUT";

if (!timedO

ut) { cause = "SIG

NALED

";// If the callback m

ethod executes because the WaitH

andle is// signaled, stop future execution of the callback m

ethod// by unregistering the W

aitHandle.

if (ti.Handle !=

null) ti.Handle.U

nregister(null); } Console.W

riteLine("WaitProc( {0} ) executes on thread {1}; cause =

{2}.",ti.O

therInfo, Thread.CurrentThread.GetH

ashCode().ToString(), cause); }}

ThreadPool

48

A. Longheu –Tecniche di programmazione avanzata

Qualche dettaglio:

�The

RegisterWaitForSingleObjectmethod queues the specified delegate

to the

thread pool.

A worker

thread will execute the delegate w

hen the specified object is in the signaled state or the tim

e-out interval elapses. �

The RegisterW

aitForSingleObject

method

checks the

current state

of the

specified object's WaitH

andle. If the object's state is unsignaled, the method

registers a wait operation. The w

ait operation is performed by a

thread from

the thread pool. The delegate is executed by a worker thread w

hen the object's state becom

es signaled or the time-out interval elapses.

�Parameters:

�waitObject: The W

aitHandle

to register.�callBack:

The WaitO

rTimerC

allbackdelegate

to call

when

the waitO

bject param

eter is signaled.�State: The object passed to the delegate.

�millisecondsTimeOutInterval: The tim

e-out in milliseconds

�executeOnlyOnce: true to indicate the thread w

ill no longer wait on the

waitO

bject parameter after the delegate has been called; false to indicate the

timer

is reset

every tim

e the

wait

operation com

pletes until

thewait

is unregistered.

�Return Value: R

egisteredWaitH

andlethat encapsulates the native handle.

ThreadPool

Page 25: Thread alessandro.longheu@diit.unict.it Alessandro … · simultanee in un programma in C#. ... quando il metodo termina ... e task. ThreadWithState tws = new ThreadWithState

49

A. Longheu –Tecniche di programmazione avanzata

�WaitH

andle Class encapsulates operating system-specific objects that

wait for exclusive access to shared resources.

�This class is typically used as a base class for synchronization

objects. Use the static m

ethods of this class to block a thread until oneor m

ore synchronization objects receive a signal.

�Altri esem

pi allegati�

Esercitazione:�

Si realizzi

un program

ma

che lancia

n thread

per cercare

un elem

ento in una matrice di n per n elem

enti. Ognuno dei thread

cerca l'elemento in una delle righe della m

atrice. Non appena un

thread ha trovato l'elemento cercato, rende note agli altri thread le

coordinate dell'elemento e tutti i thread term

inano. �

Risolvere il problem

a dei cinque filosofi�

Realizzare un server che rim

ane in ascolto di richieste dai client (sim

ulare il

tutto in

localhost); ad

ogni richiesta

di un

client, sganciare un thread che ne soddisfi le richieste, m

entre il thread principale torna in ascolto di nuove connessioni

ThreadPool