ynchronizedaitotifyotifyAllfsystemutaitPosixotifyPosixnittarttopestroy

Planche 1

Inf 431 -- Cours 12
Sémaphores
Appliquettes


http://jeanjacqueslevy.net
secrétariat de l'enseignement:
Catherine Bensoussan
cb@lix.polytechnique.fr
Aile 00, LIX,
01 69 33 34 67
http://www.enseignement.polytechnique.fr/informatique/IF

Planche 2

Plan


.6@percent
  1. Algorithme de Peterson
  2. Sémaphores booléennes
  3. Sémaphores généralisées
  4. Producteur -- Consommateur
  5. Les 5 philosophes
  6. Appliquettes Java
  7. Synchronisation par envois de messages
  8. Modèle client/serveur

Bibliographie

Mordechai Ben-Ari, Principles of Concurrent Programming, Prentice Hall, 1982.

J. Misra and K. M. Chandy, Parallel Program Design: A Foundation, Addison-Wesley, 1988.


Planche 3

Algorithme de Peterson (1/5)


class Peterson extends Thread {
  static int tour = 0;
  static boolean[ ] actif  = {falsefalse};
  int i, j;
  Peterson (int x) { i = x; j = 1 - x; }

  public void run() {
    while (true) {
      actif[i] = true;
      tour = j;
      while (actif[j] && tour  == j)
        ;
      // section critique
      actif[i] = false;
  } }

  public static void main (String[ ] args) {
    Thread t0 = new Peterson(0), t1 = new Peterson(1);
    t0.start(); t1.start();
} }

Planche 4

Algorithme de Peterson (2/5)

Preuve de sureté. (safety)

Si t
0 et t1 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.

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 t0 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 t0 ou t1 ne peut rester dans le while.

Planche 5

Algorithme de Peterson (3/5)

Planche 6

Algorithme de Peterson (4/5)

Preuve de sureté:
Planche 7

Algorithme de Peterson (5/5)

Preuve de vivacité. Exercice 1 Généraliser l'algorithme de Peterson à n processus.

Planche 8

Sémaphores (1/5)

Planche 9

Sémaphores (2/5)

Exercice 2 (difficile) Programmer les variables de condition de Java avec des sémaphores.

Exercice 3 (très difficile) Programmer les variables de condition des Posix Threads avec les primitives de Java et des sémaphores.


Planche 10

Sémaphores (2/5)

Planche 11

Sémaphores (3/5)

Avec les sémaphores, on peut programmer la file d'attente concurrente de longueur 1. Au début \s_vide = true, s_plein = false.
  static void ajouter (int x, FIFO f) {
    P(s_vide);
    f.contenu = x;
    f.pleine = true;
    V(s_plein);
  }
  
  static int supprimer (FIFO f) {
    int res;
    P(s_plein);
    res = f.contenu;
    f.pleine = false;
    V(s_vide);
    return res;
  }

Planche 12

Sémaphores (4/5)

Pour programmer la file de longueur n, il est plus simple de se servir de la notion de sémaphore généralisé. En première approximation, un sémaphore booléen est un sémaphore initialisé à 1.

Exercice 4 Montrer que la remarque précédente n'est pas tout à fait exacte.


Planche 13

Sémaphores (5/5)

Soit n la taille de la file. Au début, s_libres=n et s_occupes=0.
  static void ajouter (int x, FIFO f) {
    P(s_libres);
    synchronized (f) {
      f.contenu[f.fin] = x;
      f.fin = (f.fin + 1) % f.contenu.length;
      f.vide = false; f.pleine = f.fin == f.debut;
    }
    V(s_occupes);
  }

  static int supprimer (FIFO f) {
    P(s_occupes);
    synchronized (f) {
      int res = f.contenu[f.debut];
      f.debut =  (f.debut + 1) % f.contenu.length;
      f.vide = f.fin == f.debut; f.pleine = false;
    }
    V(s_libres);
    return res;
  }

Problème dit du producteur - consommateur.

Planche 14

Les 5 philosophes (1/7)

Planche 15

Les 5 philosophes (2/7)


  static Semaphore[ ] s = new Semaphore[5];
  Philosophe (int x) { i = x; }
  int i;

  public void run() {
    while (true) {
      // penser
      Semaphore.P(s[i]);
      Semaphore.P(s[(i+1)%5]);
      // manger
      Semaphore.V(s[i]);
      Semaphore.V(s[(i+1)%5]);
  } }

  public static void main (String[ ] args) {
    for (int i = 0; i < s.length; ++i) {
      Philosophe phi = new Philosophe(i);
      phi.start();
} } }

Sureté, mais interblocage.


Planche 16

Les 5 philosophes (3/7)


  static int[ ] f = {2, 2, 2, 2, 2};
  static ConditionPosix[ ] manger = new ConditionPosix[5];
  int i;

  Philosophe1 (int x) { i = x; }

  ...

  public static void main (String[ ] args) {
    for (int i = 0; i < f.length; ++i) {
      Philosophe1 phi = new Philosophe1(i);
      phi.start();
} } }
Planche 17

Les 5 philosophes (4/7)

    while (f[i] != 2)
      waitPosix (manger[i]);
    -- f[(i-1) % 5]; -- f[(i+1) % 5];
  }

  static synchronized void relacherFourchettes(int i) {
    int g = (i-1) % 5, d = (i+1) % 5;
    ++ f[g]; ++ f[d];
    if (f[d] == 2)
      notifyPosix (manger[d]);
    if (f[g] == 2)
      notifyPosix (manger[g]);
  }

  public void run() {
    while (true) {
      // penser
      prendreFourchettes(i);
      // manger
      relacherFourchettes(i);
  } }

Planche 18

Les 5 philosophes (5/7)

Planche 19

Les 5 philosophes (6/7)

Planche 20

Les 5 philosophes (7/7)

Exercice 5 Programmer cette solution des 5 philosophes en Java, avec les seuls wait, notify et notifyAll.
(Indication: faire une classe
Fourchette avec les deux méthodes synchronisées prendre et relacher)

Planche 21

Appliquettes (1/4)

Planche 22

Appliquettes (2/4)


import java.awt.*;
import java.util.*;

public class Clock extends Applet implements Runnable {
  private Thread t;
  private boolean threadSuspended;
  final int updateInterval = 1000;
  ...
  public void init() {
    t = new Thread (this);
    t.start();
  }
  
  public void start() {
    if (threadSuspended) {
      synchronized (this) {
 threadSuspended = false;
        notify();
} } } }
Planche 23

Appliquettes (3/4)


    while (true) {
      try {
        Thread.sleep(updateInterval);
        synchronized (this) {
   while (threadSuspended)
     wait();
      } }
      catch (InterruptedException e) { }
      repaint();
  } }
  
  public void stop() { threadSuspended = true; }
  public void destroy() { }
  
  public void paint (Graphics g) {
    g.setFont(new Font("Helvetica", Font.BOLD, 14));
    g.drawString (new Date().toString(), 10, 25);
  }

Planche 24

Appliquettes (4/4)

Exercice 6 Faire une appliquette illustrant le problème des 5 philosophes.

Planche 25

Synchronisation par messages (1/5)

Planche 26

Synchronisation par messages (2/5)

Planche 27

Synchronisation par messages (3/5)

Planche 28

Synchronisation par messages (4/5)


cf. Cours systèmes d'exploitation et réseaux en majeure 2
Planche 29

Synchronisation par messages (5/5)


This document was translated from LATEX by HEVEA.