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();
}
}

© 2025-26 CentraleSupélec