Synchronisation par. Rappels. Plan. Conditions et moniteurs (1/7) Inf 431 Cours 11. jeanjacqueslevy.net



Documents pareils
J2SE Threads, 1ère partie Principe Cycle de vie Création Synchronisation

Synchro et Threads Java TM

Cours de Systèmes d Exploitation

Un ordonnanceur stupide

Exclusion Mutuelle. Arnaud Labourel Courriel : arnaud.labourel@lif.univ-mrs.fr. Université de Provence. 9 février 2011

Threads. Threads. USTL routier 1

Introduction : les processus. Introduction : les threads. Plan

Introduction à la programmation concurrente

INTRODUCTION AUX SYSTEMES D EXPLOITATION. TD2 Exclusion mutuelle / Sémaphores

Info0604 Programmation multi-threadée. Cours 5. Programmation multi-threadée en Java

Problèmes liés à la concurrence

Les processus légers : threads. Système L3, /31

Introduction à Java. Matthieu Herrb CNRS-LAAS. Mars

Cours 2: Exclusion Mutuelle entre processus (lourds, ou légers -- threads)

4. Outils pour la synchronisation F. Boyer, Laboratoire Lig

INITIATION AU LANGAGE JAVA

On appelle variable condition une var qui peut être testée et

Programmation d Applications Concurrentes et Distribuées (INF431)

Notion de thread (1/2)

Processus! programme. DIMA, Systèmes Centralisés (Ph. Mauran) " Processus = suite d'actions = suite d'états obtenus = trace

Corrigé des exercices sur les références

École Polytechnique de Montréal. Département de Génie Informatique et Génie Logiciel. Cours INF2610. Contrôle périodique.

Introduction aux Systèmes et aux Réseaux

NFP 121. Java et les Threads. Présentation : Thierry Escalarasse Mai 2007

INTRODUCTION À LA PROGRAMMATION CONCURRENTE

Projet gestion d'objets dupliqués

LOG4430 : Architecture et conception avancée

PIGOURIER Vincent ANNEE SPECIALE 99/00 RAPPORT DE PROJET : LES THREADS JAVA. Responsable : Serge Rouveyrol

Cours A7 : Temps Réel

Programmer en JAVA. par Tama

INTRODUCTION A JAVA. Fichier en langage machine Exécutable

Exercices INF5171 : série #3 (Automne 2012)

Ordonnancement temps réel

4. Outils pour la synchronisation F. Boyer, Laboratoire Sardes

Exceptions. 1 Entrées/sorties. Objectif. Manipuler les exceptions ;

Auto-évaluation Programmation en Java

Remote Method Invocation Les classes implémentant Serializable

REALISATION d'un. ORDONNANCEUR à ECHEANCES

ACTIVITÉ DE PROGRAMMATION

Introduction aux systèmes temps réel. Iulian Ober IRIT

03/04/2007. Tâche 1 Tâche 2 Tâche 3. Système Unix. Time sharing

Programmation Orientée Objet - Licence TIS CM8/9. Rappel sur la séance précédente. Lancelot Pecquet Lancelot.Pecquet@math.univ-poitiers.

Programmation avec des objets : Cours 7. Menu du jour

Info0101 Intro. à l'algorithmique et à la programmation. Cours 3. Le langage Java

Support de cours Java

Projet de programmation (IK3) : TP n 1 Correction

Gestion des processus

Premiers Pas en Programmation Objet : les Classes et les Objets

DAns un système multi-utilisateurs à temps partagé, plusieurs processus

Structure d un programme et Compilation Notions de classe et d objet Syntaxe

Corrigés des premiers exercices sur les classes

Plan du cours. Historique du langage Nouveautés de Java 7

Communication inter-processus (IPC) : tubes & sockets. exemples en C et en Java. F. Butelle

Tp 1 correction. Structures de données (IF2)

Une introduction à la technologie EJB (2/3)

La JVM. La machine virtuelle Java. La JVM. La JVM

Noyau de concurrence par moniteur pour Java ou C# pour une autre sémantique plus fiable et plus performante

as Architecture des Systèmes d Information

Java Licence Professionnelle CISII,

Informatique industrielle A Systèmes temps-réel J.F.Peyre. Partie I : Introduction

Université du Québec à Chicoutimi. Département d informatique et de mathématique. Plan de cours. Titre : Élément de programmation.

TD3: tableaux avancées, première classe et chaînes

Quelques patterns pour la persistance des objets avec DAO DAO. Principe de base. Utilité des DTOs. Le modèle de conception DTO (Data Transfer Object)

Licence Bio Informatique Année Premiers pas. Exercice 1 Hello World parce qu il faut bien commencer par quelque chose...

TD2 Programmation concurrentielle

Développement Logiciel

Chapitre 4 : Exclusion mutuelle

Programmation Par Objets

1/24. I passer d un problème exprimé en français à la réalisation d un. I expressions arithmétiques. I structures de contrôle (tests, boucles)

Exécutif temps réel Pierre-Yves Duval (cppm)

Solutions du chapitre 4

Langage et Concepts de ProgrammationOrientée-Objet 1 / 40

La carte à puce. Jean-Philippe Babau

Calcul Parallèle. Cours 5 - JAVA RMI

Conception des systèmes répartis

Objets et Programmation. origine des langages orientés-objet

Cours d Algorithmique-Programmation 2 e partie (IAP2): programmation 24 octobre 2007impérative 1 / 44 et. structures de données simples

LMI 2. Programmation Orientée Objet POO - Cours 9. Said Jabbour. jabbour@cril.univ-artois.fr

Cours intensif Java. 1er cours: de C à Java. Enrica DUCHI LIAFA, Paris 7. Septembre Enrica.Duchi@liafa.jussieu.fr

Sixième partie. Programmation multi-activités Java & Posix Threads. Généralités Java Threads POSIX Threads Autres approches

UE C avancé cours 1: introduction et révisions

OCL - Object Constraint Language

INITIATION AU LANGAGE C SUR PIC DE MICROSHIP

Cours 1 : La compilation

Gestion distribuée (par sockets) de banque en Java

Cours 1 : Introduction. Langages objets. but du module. contrôle des connaissances. Pourquoi Java? présentation du module. Présentation de Java

Bases de données et sites WEB Licence d informatique LI345

IN Cours 1. 1 Informatique, calculateurs. 2 Un premier programme en C

Partie 7 : Gestion de la mémoire

Prénom : Matricule : Sigle et titre du cours Groupe Trimestre INF1101 Algorithmes et structures de données Tous H2004. Loc Jeudi 29/4/2004

TP n 2 Concepts de la programmation Objets Master 1 mention IL, semestre 2 Le type Abstrait Pile

TD2/TME2 : Ordonnanceur et Threads (POSIX et fair)

IV- Comment fonctionne un ordinateur?

Cette application développée en C# va récupérer un certain nombre d informations en ligne fournies par la ville de Paris :

Arbres binaires de recherche

Programmation Réseau. Sécurité Java. UFR Informatique jeudi 4 avril 13

TP, première séquence d exercices.

PROGRAMMATION EVENEMENTIELLE sur EXCEL

Transcription:

Rappels Inf 431 Cours 11 un processus t (Thread) est un programme qui s exécute Synchronisation par mémoire partagée tstart lance l exécution concurrente de la méthode trun de t tinterrupt signale qu on demande l interruption de t isinterrupted teste si un signal d interruption est arrivé jeanjacqueslevynet InterruptedException est levée quand t est en attente (et ne peut pas tester isinterrupted secrétariat de l enseignement: Catherine Bensoussan cb@lixpolytechniquefr Aile 00, LIX, 01 69 33 34 67 les méthodes synchronized d un même objet s exécutent en exclusion mutuelle wait, notify, notifyall permettent la gestion concurrente de données wwwenseignementpolytechniquefr/informatique/if Plan Conditions et moniteurs (1/7) 1 Rappels 2 Conditions et moniteurs 3 Etats d un processus 4 Ordonnancement Paradigme de la concurrence la file d attente concurrente Pour simplifier, supposons la file f de longueur l tq l 1 ajouter et supprimer s exécutent de manière concurrente 5 Les lecteurs et les écrivains 6 Implémentation de la synchronisation Bibliographie Greg Nelson, Systems Programming with Modula-3, Prentice Hall, 1991 static synchronized void ajouter (int x, FIFO f) { if (fpleine) // Attendre que la file se vide fcontenu = x fpleine = true Mordechai Ben-Ari, Principles of Concurrent Programming, Prentice Hall, 1982 Fred B Schneider, On Concurrent Programming, Springer, 1997 Jean Bacon, Concurrent Systems, Addison-Wesley, 1998 SJ Leffler, MK McKusick, MJ Karels, JS Quartermann, The Design and Implementation of the 43 BSD Unix Operating System, Addison Wesley 1989 static synchronized int supprimer (FIFO f) { if (!fpleine) // Attendre que la file devienne pleine fpleine = false return fcontenu

Conditions et moniteurs (2/7) Conditions et moniteurs (4/7) ajouter attend que la file f se vide, si f est pleine supprimer attend que la file f se remplisse, si f est vide Même programme en programmation par objets il faut relâcher le verrou pour que l autre puisse s exécuter 2 solutions : ressortir de chaque méthode sans se bloquer et revenir tester la file attente active (busy wait) qui coûte cher en temps atomiquement relâcher le verrou + attendre sur une condition Quand la condition est «notifiée», on repart en reprenant le verrou en Java, une condition est une simple référence à un objet (son adresse) Par exemple, ici la file elle-même f synchronized void ajouter (int x) throws InterruptedException { while (pleine) wait() contenu = x pleine = true notify() synchronized int supprimer () throws InterruptedException { while (!pleine) wait() pleine = false notify() return contenu Exécution quand on remplit la file, on envoie un signal sur une condition et réveiller un processus en attente sur la condition Conditions et moniteurs (3/7) Conditions et moniteurs (5/7) wait et notify sont deux méthodes de la classe Object Tous les objets ont ces deux méthodes si plus de deux processus sont en jeu, notifyall réveille tous les processus en attente sur la condition static void ajouter (int x, FIFO f) throws InterruptedException { synchronized (f) { while (fpleine) fwait() fcontenu = x fpleine = true fnotify() synchronized void ajouter (int x) throws InterruptedException { while (pleine) wait() contenu = x pleine = true notifyall() static int supprimer (FIFO f) throws InterruptedException { synchronized (f) { while (!fpleine) fwait() fpleine = false fnotify() return fcontenu Exécution synchronized int supprimer () throws InterruptedException { while (!pleine) wait() pleine = false notifyall() return contenu Exécution

Conditions et moniteurs (6/7) Etats d un processus (1/3) notify n a pas de mémoire On réveille un quelconque des processus en attente sur la condition prêt exécution l action relâchant le verrou et de mise en attente engendrée par wait est atomique Sinon, on peut perdre un signal émis par notify avant d attendre sur la condition création notify() wait() mort de même notify est fait avant de relâcher le verrou il faut utiliser un while et non un if dans la section critique, car un autre processus peut être réveillé et invalider le test bloqué État prêt : un processus peut s exécuter État exécution : un processus qui s exécute (currentthread) État bloqué : on attend sur une condition Un signal émis sur une condition peut réveiller le processus et le faire passer dans l état prêt Conditions et moniteurs (7/7) Etats d un processus (2/3) class FIFO { int debut, fin boolean pleine, vide int[ ] contenu synchronized void ajouter (int x) throws InterruptedException { while (pleine) wait() contenu[fin] = x fin = (fin + 1) % contenulength vide = false pleine = fin == debut notifyall() synchronized int supprimer () throws InterruptedException { while (vide) wait() int res = contenu[debut] debut = (debut + 1) % contenulength vide = fin == debut pleine = false notifyall() return res Exécution Il peut y avoir plus de processus prêts que de processeurs Les processus prêts forment un ensemble, souvent géré comme une FIFO ou une file de priorités (runq) Le système (la JVM) en choisit un pour l exécution Lequel? C est le problème de l ordonnancement des processus (scheduling) Systèmes préemptifs peuvent arrêter un processus en cours d exécution et le mettre dans l état prêt Systèmes non préemptifs attendent qu un processus relâche le processeur (par Threadyield()) Dans les systèmes non préemptifs, les processus fonctionnent en coroutines

Etats d un processus (3/3) création prêt : start() prêt exécution : ordonnanceur (scheduler) exécution prêt : Threadyield() ou fin d un quantum de temps (pour systèmes préemptifs) exécution bloqué : wait(), début de synchronized bloqué prêt : réveil sur notify() ou notifyall(), fin de synchronized exécution mort : fin de run() Ordonnancement (2/2) priorité sur l age Au début, p = p 0 est la priorité statique donnée au processus Si un processus prêt attend le processeur pendant k secondes, on incrémente p Quand il s exécute, on fait p = p 0 priorité décroit si on utilise beaucoup de processeur (Unix 43BSD) Au début p = PUSER + 2p nice est la priorité initiale statique Tous les 40ms, la priorité est recalculée par : pcpu p = PUSER + + 2 p nice 4 Tous les 10 ms, p cpu est incrémenté quand le processus s exécute Toutes les secondes, p cpu est aussi modifié par le filtre suivant : p cpu = 2 load 2 load + 1 p cpu + p nice qui fait baisser sa valeur en fonction de la charge globale du système load (nombre moyen de processus prêts sur la dernière minute) Pour Unix, la priorité croit dans l ordre inverse de sa valeur (0 est fort, 127 est bas) Ordonnancement (1/2) Synchronisation et priorités Priorités statiques Les méthodes getpriority et setpriority donnent les valeurs de la priorité d un processus Avec les verrous pour l exclusion mutuelle, une inversion de priorités est possible Les priorités suivantes MIN_PRIORITY, NORM_PRIORITY, MAX_PRIORITY sont prédéfinies 3 processus P b, P m, P h s exécutent en priorité basse, moyenne, et haute En fait, l ordonnanceur peut aussi affecter des priorités dynamiques pour avoir une politique d allocation du (des) processeur(s) La spécification de Java dit qu en général les processus de forte priorité vont s exécuter avant les processus de basse priorité L important est d écrire du code portable comprendre ce que la JVM garantit sur tous les systèmes Ecrire du code contrôlant l accès à des variables partagées en faisant des hypothèses sur la priorité des processus ou sur leur vitesse relative (race condition) est très dangereux P b prend un verrou qui bloque P h P m s exécute et empêche P b (de priorité plus faible) de s exécuter le verrou n est pas relâché et un processus de faible priorité P m peut empêcher le processus P h de s exécuter on peut s en sortir en affectant des priorités sur les verrous en notant le processus de plus haute priorité attendant sur ce verrou Alors on fait monter la priorité d un processus ayant pris ce verrou (Win 2000) tout cela est dangereux

Les lecteurs et les écrivains (1/6) Les lecteurs et les écrivains (3/6) Une ressource partagée est lue ou modifiée concurremment En lecture, la ressource n est pas modifiée notifyall réveille trop de processus se retrouvant immédiatement bloqués Avec des variables de condition Posix clecture et cecriture, on a un contrôle plus fin : Plusieurs processus (lecteurs) peuvent lire simultanément la donnée Un seul processus (écrivain) peut modifier la donnée Quand un lecteur s exécute, aucun écrivain ne peut s exécuter en parallèle Quand un écrivain s exécute, aucun autre écrivain, ni aucun lecteur, ne peut s exécuter void lecture() { accespartage() // lire la donnée partagée retourpartage() void ecriture() { accesexclusif() // modifier la donnée partagée retourexclusif() synchronized void accespartage() { ++ nlecteursenattente while (nlecteurs == -1) waitposix(clecture) -- nlecteursenattente ++ nlecteurs synchronized void retourpartage() { -- nlecteurs if (nlecteurs == 0) notifyposix(cecriture) Les conditions Posix n existent pas en Java!! Elles existent en C, C++, Ocaml, Modula-3, ADA, etc synchronized void accesexclusif() { while (nlecteurs!= 0) waitposix(cecriture) nlecteurs = -1 synchronized void retourexclusif() { nlecteurs = 0 if (nlecteursenattente > 0) notifyallposix(clecture) else notifyposix(cecriture) Les lecteurs et les écrivains (2/6) En lecture, on a nlecteurs simultanés (nlecteurs > 0) En écriture, on a nlecteurs = 1 synchronized void accespartage() { while (nlecteurs == -1) wait() ++ nlecteurs synchronized void retourpartage() { -- nlecteurs if (nlecteurs == 0) notify() synchronized void accesexclusif() { while (nlecteurs!= 0) wait() nlecteurs = -1 synchronized void retourexclusif() { nlecteurs = 0 notifyall() Les lecteurs et les écrivains (4/6) Exécuter notify à l intérieur d une section critique n est pas très efficace Avec un seul processeur, ce n est pas un problème car les réveillés passent dans l état prêt attendant la disponibilité du processeur Avec plusieurs processeurs, le processus réveillé peut retomber rapidement dans l état bloqué, tant que le verrou n est pas relâché Il vaut mieux faire notify à l extérieur de la section critique (Ce qu on ne fait jamais!), ou au moment de la sortie du synchronized : void retourpartage() { boolean fairenotify synchronized (this) { -- nlecteurs fairenotify = nlecteurs == 0 if (fairenotify) notifyposix(cecriture)

Les lecteurs et les écrivains (5/6) Des blocages inutiles sont possibles (avec plusieurs processeurs) sur le notifyall de fin d écriture Comme avant, on peut le sortir de la section critique Si plusieurs lecteurs sont réveillés, un seul prend le verrou Mieux vaut faire notify en fin d écriture, puis refaire notify en fin d accès partagé pour relancer les autres lecteurs void accespartage() { synchronized (this) { ++ nlecteursenattente while (nlecteurs == -1) waitposix(clecture) -- nlecteursenattente ++ nlecteurs notifyposix(clecture) synchronized void retourexclusif() { nlecteurs = 0 if (nlecteursenattente > 0) notifyposix(clecture) else notifyposix(cecriture) Exclusion mutuelle : implémentation (1/4) Comment réaliser une opération atomique? Comment implémenter la prise d un verrou? ou l attente sur une condition? Dépend du matériel Souvent sur un ordinateur, il a une instruction machine ininterruptible Test and Set TAS(m) teste si m = 0 Si oui, alors on répond vrai et on met m à 1 Sinon on répond faux On programme une section critique ainsi : while (TAS(m) == false) m = 0 attente active beaucoup de temps machine (spin locks) Parfois, des adresses mémoire particulières servent de verrous Leur lecture/écriture est atomique (ininterruptible) Les lecteurs et les écrivains (6/6) Famine possible d un écrivain en attente de fin de lecture La politique d ordonnancement des processus peut aider On peut aussi logiquement imposer le passage d un écrivain void accespartage() { synchronized (this) { ++ nlecteursenattente if (necrivainsenattente > 0) waitposix(clecture) while (nlecteurs == -1) waitposix(clecture) -- nlecteursenattente ++ nlecteurs notifyposix(clecture) synchronized void accesexclusif() { ++ necrivainsenattente while (nlecteurs!= 0) waitposix(cecriture) -- necrivainsenattente nlecteurs = -1 Exclusion mutuelle : implémentation (2/4) Au lieu de faire une attente active, on range le processus dans un ensemble de processus en attente sur la libération d un verrou Souvent, cet ensemble W m de processus en attente est une FIFO Mais tenir compte que c est une FIFO est non portable while (TAS(mverrou) == false) Ranger currentthread dans W m Attendre sur m mval = 0 Signaler sur m Attendre et Signaler sont ici des opérations internes à la JVM Contrôler finement la synchronisation peut être complexe

Exclusion mutuelle : implémentation (3/4) Sans TAS, peut-on y arriver? Solution injuste while (tour!= 0) tour = 1 while (tour!= 1) tour = 0 Solution fausse (cf la réservation des places d avions) while (actif[1]) while (actif[0]) actif[0] = true actif[1] = true actif[0] = false actif[1] = false Algorithme de Peterson (1/5) class Peterson extends Thread { static int tour = 0 static boolean[ ] actif = {false, false int i, j Peterson (int x) { i = x j = 1 - x public void run() { actif[i] = true tour = j while (actif[j] && tour == j) actif[i] = false public static void main (String[ ] args) { Thread t0 = new Peterson(0), t1 = new Peterson(1) t0start() t1start() Exclusion mutuelle : implémentation (4/4) Algorithme de Peterson (2/5) Solution avec interblocage actif[0] = true while (actif[1]) actif[0] = false actif[1] = true while (actif[0]) actif[1] = false Preuve de sureté (safety) Si t 0 et t 1 sont tous les deux dans leur section critique Alors actif [0] = actif [1] = true Impossible car les deux tests auraient été franchis en même temps alors que tour favorise l un deux Donc un seul est entré Disons t 0 Cela veut dire que t 1 n a pu trouver le tour à 1 et n est pas entré en section critique Solution correcte possible? algorithmes de [Dekker, Peterson] Preuve de vivacité (lifeness) Supposons t 0 bloqué dans le while Cas 1 : t 1 non intéressé à rentrer dans la section critique Alors actif [1] = false Et donc t 0 ne peut être bloqué par le while Cas 2 : t 1 est aussi bloqué dans le while Impossible car selon la valeur de tour, l un de t 0 ou t 1 ne peut rester dans le while

Algorithme de Peterson (3/5) Algorithme de Peterson (5/5) avec des assertions où on fait intervenir la ligne des programmes c 0 et c 1 (compteur ordinal) exécutée par t 0 et t 1 public void run() { { actif [i] c i 2 1 actif[i] = true {actif [i] c i = 2 2 tour = j {actif [i] c i 2 3 while (actif[j] && tour == j) {actif [i] c i 2 ( actif [j] tour = i c j = 2) // fin de section critique 5 actif[i] = false { actif [i] c i 2 6 Threadyield() Preuve de vivacité Si t 0 et t 1 dans la boucle while : actif [1] tour = 1 actif [0] tour = 0 tour = 0 tour = 1 P false Si t 0 en dehors de la boucle while et t 1 dedans, la preuve se complique car faisant intervenir l évolution dans le temps (logique temporelle ou modale) Par exemple : équivaut à actif [0] tour = 0 actif [0] c 0 = 2 actif [0] tour = 0 c 0 = 2 alors le programme évolue vers tour = 1 et le tout devient faux On quitte donc la boucle while Algorithme de Peterson (4/5) Exercices Preuve de sureté : Si t 0 et t 1 sur la ligne 5, on a : actif [0] c 0 2 ( actif [1] tour = 0 c 1 = 2) actif [1] c 1 2 ( actif [0] tour = 1 c 0 = 2) Exercice 1 Dans le langage Ada, la communication se fait par rendez-vous Deux processus P et Q font un rendez-vous s ils s attendent mutuellement chacun à un point de son programme On peut en profiter pour passer une valeur Comment organiser cela en Java? équivaut à actif [0] c 0 2 tour = 1 actif [1] c 1 2 tour = 0 équivaut à tour = 0 tour = 1 P implique tour = 0 tour 0 P false impossible Exercice 2 Une barrière de synchronisation entre plusieurs processus est un endroit commun que tous les processus actifs doivent franchir simultanément C est donc une généralisation à n processus d un rendez-vous Comment la programmer en Java? Exercice 3 Toute variable peut être partagée entre plusieurs processus, quel est le gros danger de la communication par variables partagées? Exercice 4 Un ordonnanceur est juste s il garantit à tout processus prêt de passer dans l état exécution Comment le construire? Preuve par énumération des cas (model checking) Exercice 5 (difficile) Généraliser l algorithme de Peterson au cas de n processus (n 2)