Solution threads
EssaiThread.java
package gloo.synchronisation; public class EssaiThread extends Thread { public EssaiThread( String name ) { super( name ); } @Override public void run() { System.out.println( getName() + ": started" ); try { Thread.sleep(( int ) ( Math.random() * 1000 )); } catch( InterruptedException e ) {} System.out.println( getName() + ": finished" ); } public static void main( String[] args ) { System.out.println( "main(): started" ); EssaiThread t = new EssaiThread( "EssaiThread" ); t.start(); System.out.println( "main(): waiting" ); try { t.join(); } catch( InterruptedException e ) {} System.out.println( "main(): finished" ); } }
EssaiRunnable.java
package gloo.synchronisation; public class EssaiRunnable implements Runnable { private static Object monitor; private String name; public EssaiRunnable( String name ) { this.name = name; } @Override public void run() { System.out.println( name + ": started" ); try { Thread.sleep(( int ) ( Math.random() * 1000 )); } catch( InterruptedException e ) {} synchronized( monitor ) { System.out.println( name + ": I am the owner of the monitor" ); monitor.notify(); System.out.println( name + ": I free the monitor" ); } System.out.println( name + ": finished" ); } public static void main( String[] args ) { System.out.println( "main() started" ); monitor = new Object(); EssaiRunnable r = new EssaiRunnable( "EssaiRunnable" ); Thread t = new Thread( r ); t.start(); synchronized( monitor ) { System.out.println( "main() waiting" ); try { System.out.println( "main: before wait(), I am the owner of the monitor, but wait() will free it" ); monitor.wait(); System.out.println( "main: after wait(), I am again the owner of the monitor, I will free it" ); } catch( InterruptedException e ) {} } System.out.println( "main() finished" ); } }
BoiteALettres.java
package gloo.synchronisation; /* * Version sans synchronisation */ public class BoiteALettres { private int[] boite; private int indiceDepot = 0; private int indiceRetrait = 0; public BoiteALettres( int taille ) { this.boite = new int[taille]; } public void depot( int val ) { boite[indiceDepot] = val; indiceDepot = ( indiceDepot + 1 ) % boite.length; } public int retrait() { int val = boite[indiceRetrait]; boite[indiceRetrait] = 0; indiceRetrait = ( indiceRetrait + 1 ) % boite.length; return val; } }
Producteur.java
package gloo.synchronisation; public class Producteur extends Thread { private BoiteALettres boite; private int nombreMessages; public Producteur( BoiteALettres boite, int nombreMessages ) { super(); this.boite = boite; this.nombreMessages = nombreMessages; } public void run() { for( int i = 1; i <= nombreMessages; ++i ) { try { Thread.sleep(( int ) ( Math.random() * 1000 )); } catch( InterruptedException e ) {} System.out.println( "Depot de " + i ); boite.depot( i ); } } }
Consommateur.java
package gloo.synchronisation; public class Consommateur extends Thread { private BoiteALettres boite; private int nombreMessages; public Consommateur( BoiteALettres boite, int nombreMessages ) { super(); this.boite = boite; this.nombreMessages = nombreMessages; } public void run() { for( int i = 1; i <= nombreMessages; ++i ) { try { Thread.sleep(( int ) ( Math.random() * 1000 )); } catch( InterruptedException e ) {} int val = boite.retrait(); if( val <= 0 ) { System.out.println( "Erreur lors du retrait : " + val + " obtenu" ); } else { System.out.println( "Retrait de " + val ); } } } }
BoiteALettresAvecMoniteur.java
package gloo.synchronisation; /* * Version suspendant le consommateur si la boite est vide * et le producteur si la boite est pleine */ public class BoiteALettresAvecMoniteur extends BoiteALettres { public BoiteALettresAvecMoniteur( int taille ) { super( taille ); } private int nombreMessages = 0; @Override public synchronized void depot( int val ) { try { // Si vous utilisez un if ici, il y aura des problèmes // avec plusieurs producteurs // getTaille : méthode ajoutée à BoiteALettres while( nombreMessages == getTaille() ) { System.out.println( "Le producteur attend" ); wait(); System.out.println( "Le producteur est reveille" ); } } catch( InterruptedException e ) { e.printStackTrace(); } super.depot( val ); ++nombreMessages; notify(); } @Override public synchronized int retrait() { try { // Si vous utilisez un if ici, il y aura des problèmes // avec plusieurs consommateurs while( nombreMessages == 0 ) { System.out.println( "Le consommateur attend" ); wait(); System.out.println( "Le consommateur est reveille" ); } } catch( InterruptedException e ) { e.printStackTrace(); } --nombreMessages; notify(); return super.retrait(); } }
Main.java (V1)
package gloo.synchronisation; /* * Version 1 producteur et 1 consommateur */ public class Main { private static final int TAILLE_BOITE = 2; private static final int NOMBRE_MESSAGES = 10; public static void main( String[] args ) { BoiteALettres boite = new BoiteALettresAvecMoniteur( TAILLE_BOITE ); Producteur p = new Producteur( boite, NOMBRE_MESSAGES ); Consommateur c = new Consommateur( boite, NOMBRE_MESSAGES ); p.start(); c.start(); try { p.join(); c.join(); } catch( InterruptedException e ) {} } }
Main.java (V2)
package gloo.synchronisation; /* * Version 2 producteurs et 1 consommateur */ public class Main { private static final int TAILLE_BOITE = 2; private static final int NOMBRE_MESSAGES = 10; public static void main( String[] args ) { BoiteALettres boite = new BoiteALettresAvecMoniteur( TAILLE_BOITE ); Producteur p1 = new Producteur( boite, NOMBRE_MESSAGES ); Producteur p2 = new Producteur( boite, NOMBRE_MESSAGES ); Consommateur c = new Consommateur( boite, NOMBRE_MESSAGES * 2 ); p1.start(); p2.start(); c.start(); try { p1.join(); p2.join(); c.join(); } catch( InterruptedException e ) {} } }
BoiteALettresAvecSemaphore.java (V1)
package gloo.synchronisation; import java.util.concurrent.Semaphore; public class BoiteALettresAvecSemaphore extends BoiteALettres { private Semaphore placesLibres; private Semaphore placesOccupees; public BoiteALettresAvecSemaphore( int taille ) { super( taille ); placesLibres = new Semaphore( taille ); placesOccupees = new Semaphore( 0 ); } @Override public void depot( int val ) { try { placesLibres.acquire(); } catch( InterruptedException e ) {} super.depot( val ); placesOccupees.release(); } @Override public int retrait() { try { placesOccupees.acquire(); } catch( InterruptedException e ) {} int val = super.retrait(); placesLibres.release(); return val; } }
BoiteALettresAvecSemaphore.java (V2)
package gloo.synchronisation; import java.util.concurrent.Semaphore; public class BoiteALettresAvecSemaphore extends BoiteALettres { private Semaphore placesLibres; private Semaphore placesOccupees; // Deux sémaphores d'exclusion mutuelle pour protéger des dépôts et retraits simultanés // Une autre solution est que les deux méthodes de BoiteALettres soient synchronized private Semaphore protectionDepot = new Semaphore( 1 ); private Semaphore protectionRetrait = new Semaphore( 1 ); public BoiteALettresAvecSemaphore( int taille ) { super( taille ); placesLibres = new Semaphore( taille ); placesOccupees = new Semaphore( 0 ); } @Override public void depot( int val ) { try { placesLibres.acquire(); protectionDepot.acquire(); } catch( InterruptedException e ) {} super.depot( val ); protectionDepot.release(); placesOccupees.release(); } @Override public int retrait() { try { placesOccupees.acquire(); protectionRetrait.acquire(); } catch( InterruptedException e ) {} int val = super.retrait(); protectionRetrait.release(); placesLibres.release(); return val; } }
Information.java
package gloo.synchronisation.lecteurredacteur; public class Information { private int nombreLecteurs = 0; private boolean redacteurPresent = false; public synchronized void accesLecture() { System.out.println( "Demande d'accès en lecture par " + Thread.currentThread().getName() ); if( nombreLecteurs == 0 ) { try { while( redacteurPresent ) { System.out.println( "Attente pour l'accès en lecture par " + Thread.currentThread().getName() ); wait(); } } catch( InterruptedException e ) {} } ++nombreLecteurs; System.out.println( "Accès en lecture accordé à " + Thread.currentThread().getName() ); } public synchronized void finLecture() { System.out.println( "Fin de l'accès en lecture par " + Thread.currentThread().getName() ); --nombreLecteurs; if( nombreLecteurs == 0 ) notify(); } public synchronized void accesEcriture() { System.out.println( "Demande d'accès en écriture par " + Thread.currentThread().getName() ); try { while( redacteurPresent || nombreLecteurs > 0 ) { System.out.println( "Attente pour l'accès en écriture par " + Thread.currentThread().getName() ); wait(); } } catch( InterruptedException e ) {} redacteurPresent = true; System.out.println( "Accès en écriture accordé à " + Thread.currentThread().getName() ); } public synchronized void finEcriture() { System.out.println( "Fin de l'accès en ecriture par " + Thread.currentThread().getName() ); redacteurPresent = false; // Il est important de réveiller ici tous les lecteurs (pas seulement 1) notifyAll(); } }

© 2022-23 CentraleSupélec