43
Systèmes d’Exploitation chapitre 7 Moniteurs F. Moal 2012/2013

Systèmes d’Exploitationthebear45.free.fr/miage/Master 1/Système/Cours/ch7... · 2013. 12. 9. · 2 façons de créer des threads Java : 1) créer une instance d’une classe fille

  • Upload
    others

  • View
    1

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Systèmes d’Exploitationthebear45.free.fr/miage/Master 1/Système/Cours/ch7... · 2013. 12. 9. · 2 façons de créer des threads Java : 1) créer une instance d’une classe fille

Systèmes d’Exploitation

chapitre 7

Moniteurs

F. Moal

2012/2013

Page 2: Systèmes d’Exploitationthebear45.free.fr/miage/Master 1/Système/Cours/ch7... · 2013. 12. 9. · 2 façons de créer des threads Java : 1) créer une instance d’une classe fille

2

Moniteurs

Gestion des contraintes de synchronisation

et d’exclusion mutuelle

par : BRINCH HANSEN, HOARE 1973

But : décharger le programmeur de la gestion explicite de

l’exclusion mutuelle

Page 3: Systèmes d’Exploitationthebear45.free.fr/miage/Master 1/Système/Cours/ch7... · 2013. 12. 9. · 2 façons de créer des threads Java : 1) créer une instance d’une classe fille

3

Moniteurs

Idée de départ: Encapsulation

Var r: ressource

Process p;

with r do <section critique>

with r do <section critique>

End p;

Page 4: Systèmes d’Exploitationthebear45.free.fr/miage/Master 1/Système/Cours/ch7... · 2013. 12. 9. · 2 façons de créer des threads Java : 1) créer une instance d’une classe fille

4

Moniteurs

Moniteur : type abstrait de données [classe]

Encapsulation

- Variables

- Opérations [méthodes]

- Conditions

Condition : évènement dont on attend la réalisation

Ex: tampon_vide / tampon_plein

Page 5: Systèmes d’Exploitationthebear45.free.fr/miage/Master 1/Système/Cours/ch7... · 2013. 12. 9. · 2 façons de créer des threads Java : 1) créer une instance d’une classe fille

5

Moniteurs

A chaque condition C d’un moniteur sont

associées 3 opérations :

C.attendre [C.wait] : met en attente le processus

qui l’exécute (une file d’attente par condition)

C.vide : faux s’il existe un ou plusieurs

processus en attente de C, vrai sinon

C.signaler [C.signal] : réveille un unique

processus en attente de C, s’il existe.

Page 6: Systèmes d’Exploitationthebear45.free.fr/miage/Master 1/Système/Cours/ch7... · 2013. 12. 9. · 2 façons de créer des threads Java : 1) créer une instance d’une classe fille

6

Moniteurs: spécification

La spécification des moniteurs fournit

gratuitement l’exclusion mutuelle

Règle 1 : les variables du moniteur ne sont

accessibles QUE par l’intermédiaire des

procédures et fonctions du moniteur [=variables

privées]

Règle 2 : le moniteur entier est implanté comme

une section critique

Page 7: Systèmes d’Exploitationthebear45.free.fr/miage/Master 1/Système/Cours/ch7... · 2013. 12. 9. · 2 façons de créer des threads Java : 1) créer une instance d’une classe fille

7

Moniteurs: spécification

La spécification des moniteurs fournit gratuitement

l’exclusion mutuelle

A un instant donné, au plus UN processus peut être à

l’intérieur du moniteur c-à-d en train d’exécuter une

procédure ou fonction du moniteur.

Lorsqu’un processus demande l’exécution d’une procédure

P du moniteur, 2 possibilités :

1. Aucun autre processus n’est déjà à l’intérieur du moniteur : la

procédure est exécutée

2. Un processus exécute déjà une des procédures ou fonctions du

moniteur : le processus appelant est mis en attente du moniteur et

sera réveillé lorsque le moniteur redeviendra disponible

Page 8: Systèmes d’Exploitationthebear45.free.fr/miage/Master 1/Système/Cours/ch7... · 2013. 12. 9. · 2 façons de créer des threads Java : 1) créer une instance d’une classe fille

8

Moniteurs: utilisation

Idée : déclarer toutes les variables

partagées dans un moniteur

Sémaphore de synchronisation condition

Sémaphore d’exclusion mutuelle disparition !

Chaque exécution d’une procédure du moniteur

est une opération atomique

Page 9: Systèmes d’Exploitationthebear45.free.fr/miage/Master 1/Système/Cours/ch7... · 2013. 12. 9. · 2 façons de créer des threads Java : 1) créer une instance d’une classe fille

9

Moniteurs: utilisation

Exemple 1 :

P produit a

fin(P) ≤ début(Q)

Q utilise a

synchro : Moniteur

fait : booléen

fini : condition

Procédure fin_production

fait = vrai

fini.signaler

Procédure début_utilisation

si (!fait) alors fini.attendre

Initialisation

fait = faux

P Q

fait

Page 10: Systèmes d’Exploitationthebear45.free.fr/miage/Master 1/Système/Cours/ch7... · 2013. 12. 9. · 2 façons de créer des threads Java : 1) créer une instance d’une classe fille

10

Moniteurs: utilisation

synchro : Moniteur

fait : booléen

fini : condition

Procédure fin_production

fait = vrai

fini.signaler

Procédure début_utilisation

si (!fait) alors fini.attendre

Initialisation

fait = faux

P :: produire(objet) Q :: synchro.début_utilisation()

synchro.fin_production() utiliser(objet)

Rem : en ADA, moniteur = type protected

en Java : synchronised (cf plus loin)

P Q

fait

Page 11: Systèmes d’Exploitationthebear45.free.fr/miage/Master 1/Système/Cours/ch7... · 2013. 12. 9. · 2 façons de créer des threads Java : 1) créer une instance d’une classe fille

11

Moniteurs: utilisation

Exemple 2 : Rendez-vous

N processus se donnent Rendez-vous en un point donné

: avant de continuer leurs exécutions, ils doivent

attendre que TOUS soient arrivés au pt de Rendez-

vous.

Idée :

Quand un processus arrive au point de RV, il

s’enregistre (n=n+1)

tant que n<N [tous là] attendre

Page 12: Systèmes d’Exploitationthebear45.free.fr/miage/Master 1/Système/Cours/ch7... · 2013. 12. 9. · 2 façons de créer des threads Java : 1) créer une instance d’une classe fille

12

Moniteurs: utilisation

RV : Moniteur

n : entier

touslà : condition

Procédure arrivée

n = n +1

si (n<N) alors touslà.attendre

sinon touslà.signaler

Initialisation

n = 0

Page 13: Systèmes d’Exploitationthebear45.free.fr/miage/Master 1/Système/Cours/ch7... · 2013. 12. 9. · 2 façons de créer des threads Java : 1) créer une instance d’une classe fille

13

Moniteurs: utilisation

Exemple 3 : Gestion de ressources banalisées

Par ex, tampons d’Entrée/Sortie

A chaque fois qu’un processus lit un fichier, un tampon

d’E/S lui est alloué

Chaque process a besoin d’autant de tampons que de

fichiers ouverts

Il y a pool fini de tampons dans le système : variable

partagée nlibre

Demander(n) pour se voir allouer n tampons

Libérer(n) pour remettre les tampons dans le pool

Page 14: Systèmes d’Exploitationthebear45.free.fr/miage/Master 1/Système/Cours/ch7... · 2013. 12. 9. · 2 façons de créer des threads Java : 1) créer une instance d’une classe fille

14

Moniteurs: utilisation

ressource : Moniteur

nlibre : entier

dispo : condition

Procédure demander(n)

si (n>nlibre) alors disp.attendre

nlibre = nlibre -n

Procédure liberer(n)

nlibre = nlibre + n

disp.signaler

Initialisation

nlibre = N

Page 15: Systèmes d’Exploitationthebear45.free.fr/miage/Master 1/Système/Cours/ch7... · 2013. 12. 9. · 2 façons de créer des threads Java : 1) créer une instance d’une classe fille

15

Moniteurs: utilisation

Pb1

au moment du réveil, le processus réveilleur (celui qui fait signaler) ne peut pas garantir que la condition attendre est devenue vraie !

Donc il faut faire un tant que au lieu d’un si : l’attente doit être conditionnée par un tant que

Pb2

pour avoir un réveil en chaîne, ajouter dispo.signaler

Page 16: Systèmes d’Exploitationthebear45.free.fr/miage/Master 1/Système/Cours/ch7... · 2013. 12. 9. · 2 façons de créer des threads Java : 1) créer une instance d’une classe fille

16

Moniteurs: utilisation

Modification du moniteur :

Gérer une file des demandes des processus

Associer une condition à chaque processus

pour pouvoir effectuer un réveil sélectif

Page 17: Systèmes d’Exploitationthebear45.free.fr/miage/Master 1/Système/Cours/ch7... · 2013. 12. 9. · 2 façons de créer des threads Java : 1) créer une instance d’une classe fille

17

Moniteurs: utilisation

Exemple 4 : Exclusion mutuelle

placer l’indicateur occupé dans un moniteur pour éviter

les conflits de lecture/écriture

mutex : Moniteur

occupé : booléen

libre : condition

Procédure entrer

si occupé alors libre.attendre

occupé = vrai

Procédure sortir

occupé = faux

libre.signaler

Initialisation

occupé = faux

Page 18: Systèmes d’Exploitationthebear45.free.fr/miage/Master 1/Système/Cours/ch7... · 2013. 12. 9. · 2 façons de créer des threads Java : 1) créer une instance d’une classe fille

18

Moniteurs: utilisation

Simulation section critique :

P mutex.entrer

SC SC

V mutex.sortir

Page 19: Systèmes d’Exploitationthebear45.free.fr/miage/Master 1/Système/Cours/ch7... · 2013. 12. 9. · 2 façons de créer des threads Java : 1) créer une instance d’une classe fille

19

Moniteurs: utilisation

Exemple 5 : Problème des lecteurs/rédacteurs

un livre [fichier] partagé par deux classes de processus :

Lecteurs (R)

Rédacteurs/écrivains (W)

Contraintes de synchronisation : à un instant donné,

1 rédacteur et 0 lecteur

Ou 0 rédacteur et un nb quelconque de lecteurs

Page 20: Systèmes d’Exploitationthebear45.free.fr/miage/Master 1/Système/Cours/ch7... · 2013. 12. 9. · 2 façons de créer des threads Java : 1) créer une instance d’une classe fille

20

Moniteurs: utilisation

Variables partagées :

nl : nombre de lecteurs

ecr : vrai si écriture en cours

à encapsuler dans un moniteur

C_ecr : attente si ecr ou nl > 0

C_lect : attente si ecr

Procédures :

debut_lire

fin_lire

début_écrire

fin_écrire

Page 21: Systèmes d’Exploitationthebear45.free.fr/miage/Master 1/Système/Cours/ch7... · 2013. 12. 9. · 2 façons de créer des threads Java : 1) créer une instance d’une classe fille

21

Moniteurs: utilisation

Exemple 6 : Producteurs/consommateur

Tampon de taille N fixée

Vide ?

Plein ?

Page 22: Systèmes d’Exploitationthebear45.free.fr/miage/Master 1/Système/Cours/ch7... · 2013. 12. 9. · 2 façons de créer des threads Java : 1) créer une instance d’une classe fille

22

Moniteurs: ordre d’accès

Exécution de C.attendre à l’intérieur du moniteur, en

section critique : blocage inutile du moniteur ?

Pour ne pas le bloquer, le processus exécutant le

C.attendre est sorti du moniteur section critique

libérée

Exécution de C.signaler par P dans le moniteur qui

réveille un processus Q en attente de C : 2

processus dans le moniteur !

le reveillé Q reprend son exécution dans le

moniteur, le réveilleur P est mis en attente du

moniteur

Page 23: Systèmes d’Exploitationthebear45.free.fr/miage/Master 1/Système/Cours/ch7... · 2013. 12. 9. · 2 façons de créer des threads Java : 1) créer une instance d’une classe fille

Types de moniteurs

Il existe en fait deux types de moniteurs :

De Hoare, ceux qui viennent d’être

étudiés,

De Kessel :

Plus de Condition ni de signaler !

Juste une intruction : wait(condition

booléenne) sur les variables du moniteur

Implantés en ADA 23

Page 24: Systèmes d’Exploitationthebear45.free.fr/miage/Master 1/Système/Cours/ch7... · 2013. 12. 9. · 2 façons de créer des threads Java : 1) créer une instance d’une classe fille

24

Moniteurs en Java

Primitive de base Java pour la synchronisation:

synchronized

wait

notify / notifyAll

Règle : un moniteur est associé à CHAQUE INSTANCE d’une classe qui possède au moins une méthode du type synchronised

Java associe à chaque objet un cadenas (lock) qui sert à contrôler l’accès des threads à cet objet

Page 25: Systèmes d’Exploitationthebear45.free.fr/miage/Master 1/Système/Cours/ch7... · 2013. 12. 9. · 2 façons de créer des threads Java : 1) créer une instance d’une classe fille

25

Moniteurs en Java : pour threads !!!

2 façons de créer des threads Java :

1) créer une instance d’une classe fille de la

classe Thread ; la classe fille doit redéfinir

la méthode run()

2) utiliser le constructeur Thread(Runnable)

de la classe Thread :

1. créer un Runnable (le code qui sera contrôlé

par le contrôleur)

2. le passer au constructeur de Thread

Page 26: Systèmes d’Exploitationthebear45.free.fr/miage/Master 1/Système/Cours/ch7... · 2013. 12. 9. · 2 façons de créer des threads Java : 1) créer une instance d’une classe fille

26

class ThreadTache extends Thread {

. . .

public void run() {

// Code qui sera exécuté par le thread

. . .

}

}

...

ThreadTache threadTache = new

ThreadTache(…);

Threads : 1) par héritage

Page 27: Systèmes d’Exploitationthebear45.free.fr/miage/Master 1/Système/Cours/ch7... · 2013. 12. 9. · 2 façons de créer des threads Java : 1) créer une instance d’une classe fille

27

class Tache implements Runnable {

. . .

public void run() {

// Code qui sera exécuté par le thread

. . .

}

}

...

Tache tache = new Tache(…);

Thread t = new Thread(tache) ;

Threads : 2) par Interface

Page 28: Systèmes d’Exploitationthebear45.free.fr/miage/Master 1/Système/Cours/ch7... · 2013. 12. 9. · 2 façons de créer des threads Java : 1) créer une instance d’une classe fille

28

On appelle la méthode start() du contrôleur

de thread :

t.start();

Le code du Runnable s’exécute en parallèle

au code qui a lancé le thread

Attention ! une erreur serait d’appeler

directement la méthode run() : la méthode

run() serait exécutée par le thread qui l’a

appelée et pas par un nouveau thread

Threads : lancement

Page 29: Systèmes d’Exploitationthebear45.free.fr/miage/Master 1/Système/Cours/ch7... · 2013. 12. 9. · 2 façons de créer des threads Java : 1) créer une instance d’une classe fille

29

Moniteurs en Java : synchronized

synchronized Lorsqu’un thread rencontre la primitive

synchronized, il obtient le cadenas sur l’objet et bloque tout accès à celui-ci aux autres threads qui rencontreraient une primitive synchronized

deux utilisations possibles:

1. Comme modificateur de méthode

2. dans le code afin d’obtenir un lock sur une ressource

Page 30: Systèmes d’Exploitationthebear45.free.fr/miage/Master 1/Système/Cours/ch7... · 2013. 12. 9. · 2 façons de créer des threads Java : 1) créer une instance d’une classe fille

30

Moniteurs en Java : synchronized

1. Comme modificateur de méthode

Ceci indique alors que la méthode entière est une

section critique pour une classe

public synchronized int get() {

// section critique }

Une fois qu’un thread entre et exécute la méthode get() de l’objet, elle obtient le cadenas sur l’objet et toute tentative d’accès par un autre thread à travers une des méthodes synchronized de l’objet est alors mise en attente.

Page 31: Systèmes d’Exploitationthebear45.free.fr/miage/Master 1/Système/Cours/ch7... · 2013. 12. 9. · 2 façons de créer des threads Java : 1) créer une instance d’une classe fille

31

Moniteurs en Java : synchronized

2. dans le code afin d’obtenir un lock sur une

ressource

public void methode() {

synchronized (obj) {

// section critique

}

}

Cela permet une granularité plus fine des locks

Page 32: Systèmes d’Exploitationthebear45.free.fr/miage/Master 1/Système/Cours/ch7... · 2013. 12. 9. · 2 façons de créer des threads Java : 1) créer une instance d’une classe fille

32

Moniteurs en Java : wait / notifyAll

wait et notify/notifyAll

Dans une section critique pour libérer temporairement le cadenas qu’il possède sur un objet, un thread peut invoquer wait. Mise à part la libération du lock qui signifie qu’un autre thread peut maintenant obtenir le lock, wait a pour conséquence de mettre en attente le thread qui l’a invoqué.

Et pour réveiller des threads qui sont en attente du cadenas d’un objet, on utilisera la primitive notify (1) ou notifyAll (tous).

Page 33: Systèmes d’Exploitationthebear45.free.fr/miage/Master 1/Système/Cours/ch7... · 2013. 12. 9. · 2 façons de créer des threads Java : 1) créer une instance d’une classe fille

33

Moniteurs en Java

Exemple : Producteur / Consommateur

3 classes :

- Tampon : moniteur de synchronisation, avec

deux méthodes : put dépose et get récupère

- Producteur : thread

- Consommateur : thread

- Plus une classe de test qui lance les threads

Page 34: Systèmes d’Exploitationthebear45.free.fr/miage/Master 1/Système/Cours/ch7... · 2013. 12. 9. · 2 façons de créer des threads Java : 1) créer une instance d’une classe fille

34

Moniteurs en Java

class Tampon {

// tampon de stockage des objets produits

private static final int TAILLE = 10;

private Object [] tampon = new Object[TAILLE];

// nbre d'objets dans le tampon

private int n = 0;

...

Page 35: Systèmes d’Exploitationthebear45.free.fr/miage/Master 1/Système/Cours/ch7... · 2013. 12. 9. · 2 façons de créer des threads Java : 1) créer une instance d’une classe fille

35

Moniteurs en Java

// recupere un produit dans le tampon

public synchronized Object get(){

// tant qu’il n’y a pas de produit,

// s’endormir et attendre un réveil

while( n == 0 ){

System.out.println("dort sur get");

try {

wait();

} catch(InterruptedException e) {}

System.out.println("réveil sur get");

}

Object objet = tampon[n-1];

n = n-1;

// réveille le producteur pour qu’il produise

notifyAll();

return objet;

}

Page 36: Systèmes d’Exploitationthebear45.free.fr/miage/Master 1/Système/Cours/ch7... · 2013. 12. 9. · 2 façons de créer des threads Java : 1) créer une instance d’une classe fille

36

Moniteurs en Java

// stocke un produit dans le tampon

public synchronized void put(Object o){

// tant que le tampon est plein,

s’endormir

while( n == TAILLE-1 ){

try {

wait();

} catch(InterruptedException e) {}

}

n = n+1;

tampon[n-1] = o;

// réveil du(des) consommateur(s)

notifyAll();

}

}

Page 37: Systèmes d’Exploitationthebear45.free.fr/miage/Master 1/Système/Cours/ch7... · 2013. 12. 9. · 2 façons de créer des threads Java : 1) créer une instance d’une classe fille

37

Moniteurs en Java

public class Producteur extends Thread {

private Tampon tampon;

private int numero;

public Producteur(Tampon t, int no) {

tampon = t;

numero = no;

}

public void run() {

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

tampon.put(new Integer(i));

try {

sleep( (int)Math.random()*1000 );

} catch (InterruptedException e) {}

}

}

} // end of class Producteur

Page 38: Systèmes d’Exploitationthebear45.free.fr/miage/Master 1/Système/Cours/ch7... · 2013. 12. 9. · 2 façons de créer des threads Java : 1) créer une instance d’une classe fille

38

Moniteurs en Java

public class Consommateur extends Thread {

private Tampon tampon;

private int numero;

public Consommateur(Tampon t, int no) {

tampon = t;

numero = no;

}

public void run() {

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

Integer val = (Integer)tampon.get();

try {

sleep( (int)Math.random()*100 );

} catch (InterruptedException e) {}

}

}

} // end of class Consommateur

Page 39: Systèmes d’Exploitationthebear45.free.fr/miage/Master 1/Système/Cours/ch7... · 2013. 12. 9. · 2 façons de créer des threads Java : 1) créer une instance d’une classe fille

39

Moniteurs en Java

public class TestProducteurConsommateur {

public static void main(String[] args) {

// un seul tampon pour tous les threads

Tampon t = new Tampon();

// création des threads prod/consommateurs

// avec des n° pour les différentier

Producteur p1 = new Producteur(t,1);

Consommateur c1 = new Consommateur(t,1);

Consommateur c2 = new Consommateur(t,2);

// lancement des threads

p1.start();

c1.start();

c2.start();

}

} // end of class TestProducteurConsommateur

Page 40: Systèmes d’Exploitationthebear45.free.fr/miage/Master 1/Système/Cours/ch7... · 2013. 12. 9. · 2 façons de créer des threads Java : 1) créer une instance d’une classe fille

40

Moniteurs en Java : java 5

utiliser un seul verrou, mais avec plusieurs variables condition :

class UneClasse {

private final Lock lock = new ReentrantLock();

private final Condition cond1 = lock.newCondition();

private final Condition cond2 = lock.newCondition();

...

Page 41: Systèmes d’Exploitationthebear45.free.fr/miage/Master 1/Système/Cours/ch7... · 2013. 12. 9. · 2 façons de créer des threads Java : 1) créer une instance d’une classe fille

41

Moniteurs en Java : java 5

...void methode1() throws InterruptedException {

lock.lock();

try {

cond1.await();

cond2.signal();

} finally {

lock.unlock();

}

}

void methode2() throws InterruptedException {

lock.lock();

try {

cond1.signal();

cond2.await();

} finally {

lock.unlock();

}

}

Page 42: Systèmes d’Exploitationthebear45.free.fr/miage/Master 1/Système/Cours/ch7... · 2013. 12. 9. · 2 façons de créer des threads Java : 1) créer une instance d’une classe fille

42

Moniteurs en Java : java 5

Introduction d’une classe Sémaphore :

Semaphore sem = new Semaphore(1);

try {

sem.acquire();

//section critique

sem.release();

} catch(InterruptedException e) {

e.printStackTrace();

}

Page 43: Systèmes d’Exploitationthebear45.free.fr/miage/Master 1/Système/Cours/ch7... · 2013. 12. 9. · 2 façons de créer des threads Java : 1) créer une instance d’une classe fille

43

Moniteurs en Java : java 5/6

Le package java.util.concurrent (ainsi que ses sous-packages) fournissent des outils de synchronisation de plus haut niveau.

Par exemple, fournit une liste bloquante, implanté par BlockingQueue (liste bloquante non bornée) et ArrayBlockingQueue (liste bloquante à tampon borné).

Cf : http://docs.oracle.com/javase/tutorial/essential/concurrency/