Vous êtes sur la page 1sur 14

Smaphores et Mutex en Delphi et Java

Par Mathieu Dalbin

Date de publication : 28 septembre 2004

Dernire mise jour : 4 mars 2013

Comment utiliser des smaphores et des Mutex en Delphi et Java ?


Smaphores et Mutex en Delphi et Java par Mathieu Dalbin

I - Qu'est-ce qu'un smaphore ? Qu'est-ce qu'un Mutex ?.........................................................................................3


I-A - Principe des smaphores.............................................................................................................................. 3
I-B - Un exemple concret....................................................................................................................................... 3
I-C - Un exemple informatique...............................................................................................................................3
I-D - Principe des Mutex........................................................................................................................................ 3
II - Principe de fonctionnement................................................................................................................................... 3
II-A - Programmes, processus et threads..............................................................................................................3
II-B - Le mcanisme des smaphores...................................................................................................................4
II-C - L'approche Objet...........................................................................................................................................4
III - Programmation sous Delphi..................................................................................................................................4
III-A - Dfinition de la classe TSemaphore............................................................................................................4
III-B - Constructeur................................................................................................................................................. 5
III-C - Les principales mthodes............................................................................................................................ 5
III-D - La synchronisation sous Delphi...................................................................................................................6
IV - Programmation sous Java....................................................................................................................................7
IV-A - La classe Semaphore..................................................................................................................................7
IV-B - La synchronisation sous Java..................................................................................................................... 8
IV-C - Apparition dans Java 1.5............................................................................................................................ 8
V - Un exemple concret de Producteurs - Consommateurs....................................................................................... 8
V-A - Principe gnral............................................................................................................................................8
V-B - La Bote Aux Lettres.....................................................................................................................................8
V-C - Les Producteurs et les Consommateurs....................................................................................................11
V-D - Initialisation du mcanisme........................................................................................................................ 13
V-E - Droulement du programme.......................................................................................................................13
V-F - Programmes d'exemple.............................................................................................................................. 14
VI - Conclusion.......................................................................................................................................................... 14

-2-
Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par
les droits d'auteur. Copyright 2013 Mathieu Dalbin. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans
l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts. Cette page est dpose la SACD.
http://mdalbin.developpez.com/tutoriels/general/semaphores/
Smaphores et Mutex en Delphi et Java par Mathieu Dalbin

I - Qu'est-ce qu'un smaphore ? Qu'est-ce qu'un Mutex ?

I-A - Principe des smaphores

Un smaphore intervient donc dans le mcanisme de partage des ressources disponibles, qu'elles soient
uniques ou non, dans un environnement donn (nous parlerons ici, en priorit, d'un environnement informatique
gr par un systme d'exploitation). On trouve cependant des smaphores dans tous les domaines de la vie courante,
o les ressources doivent tre partages.

I-B - Un exemple concret

Prenons d'ores et dj un exemple concret, afin d'illustrer le fonctionnement des smaphores. Cet exemple est
destin schmatiser la situation :

Vous dcidez d'aller dans le restaurant le plus hupp de la ville (on admet, pour l'exemple, que vous pouvez aisment
vous le payer !). Lorsque vous arrivez, vous constatez que toutes les tables sont prises, et n'ayant pas rserv,
vous tes dans l'obligation d'attendre qu'une table se libre. Cette situation peut tre gre par un smaphore : ici
le type de ressource se partager est la table, le nombre de ressources est connu (par exemple 20 tables dans
ce restaurant), et toutes les ressources sont malheureusement prises et aucune n'est disponible pour vous. Vous
attendez donc qu'une ressource se libre pour la prendre, vous attendez une table pour enfin pouvoir dner !

I-C - Un exemple informatique

Ce mcanisme est similaire au sein du systme d'exploitation : prenons un exemple simple avec le disque dur. Deux
ou plusieurs programmes diffrents tentent d'accder au disque dur pour y faire plusieurs oprations d'criture et
de lecture. Ici aussi, un smaphore gre la situation : le premier des programmes accdant la ressource (qui est
unique dans ce cas, car il n'y a qu'un seul disque dur qui intresse les programmes) bloque les autres programmes
qui attendent la libration de la ressource, le disque dur dans notre cas.

I-D - Principe des Mutex

Dans ce dernier cas, on parle de Mutex, car la ressource disponible est unique. Le mot Mutex est une contraction
de Mutual Exclusion , en franais Exclusion Mutuelle , ce qui se comprend aisment : la ressource tant unique,
le premier programme y accdant bloque l'accs tous les autres, qui attendent tous que la ressource se libre. Un
Mutex se comporte donc comme un smaphore, sauf qu'il possde la particularit de grer une ressource unique.

II - Principe de fonctionnement

II-A - Programmes, processus et threads

Tout d'abord, faisons un rsum sur le vocabulaire que l'on peut rencontrer. Un smaphore, comme nous l'avons vu,
gre le partage de ressources entre plusieurs programmes. Mais ceci n'est pas tout fait vrai, si on se rfre au strict
sens des termes Un programme est avant tout compos d'un processus, au niveau du systme d'exploitation,
et un processus a pour but d'excuter des instructions. De cette faon, un processus est cr chaque excution d'un
programme excutable, ou tout autre module contenant du code machine, tel qu'une DLL ou un pilote de matriel.
Mais ce n'est pas tout car un processus est compos de threads (en franais fil , comprendre au sens
figur), dont le nombre peut tre variable. Un thread peut tre assimil une subdivision du processus, car chaque
thread est capable d'excuter des instructions et donc d'accder aux ressources de l'environnement. Tout processus
contient un thread principal (le main thread dans la littrature informatique), et peut contenir un ou plusieurs
threads secondaires. C'est ce niveau que les distinctions doivent tre faites : puisque chaque thread peut accder
aux ressources, c'est donc non pas entre processus mais entre threads que les smaphores grent les accs.

-3-
Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par
les droits d'auteur. Copyright 2013 Mathieu Dalbin. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans
l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts. Cette page est dpose la SACD.
http://mdalbin.developpez.com/tutoriels/general/semaphores/
Smaphores et Mutex en Delphi et Java par Mathieu Dalbin

Ainsi un smaphore peut trs bien grer une ressource au sein d'un mme processus,
entre, par exemple, le thread principal et un thread secondaire. De la mme faon, deux
threads n'appartenant pas au mme processus obiront aux mmes restrictions.

II-B - Le mcanisme des smaphores

Observons prsent le fonctionnement gnral d'un smaphore. D'un point de vue conceptuel, un smaphore agit
comme une porte d'accs, un point d'entre. Reprenons notre exemple du dbut, pour le restaurant : vous vous
prsentez la rception et demandez une table, le matre d'htel vous dit alors qu'il n'y a aucune table de libre et
vous demande de patienter. Si l'on devait modliser la situation dans un systme informatique, un smaphore ferait
parfaitement l'affaire pour remplacer le matre d'htel, et vous ne seriez qu'un thread parmi tant d'autres ! Ici le matre
d'htel refuse ou non votre accs une ressource qu'est une table, il joue un rle de rgulateur, en contrlant
le nombre de tables disponibles. Ce comportement est le mme pour un smaphore : chaque smaphore
contrlant un type de ressource connat chaque instant le nombre de ressources de ce type disponibles
et autorise ou refuse l'accs d'un thread une de ces ressources.

II-C - L'approche Objet

Si l'on approfondit le sujet, on constate qu'un smaphore est au final un mcanisme simple. Dans un souci de
compatibilit avec la majorit des langages modernes, nous utiliserons la conception par objet pour modliser
des smaphores et des Mutex. Ainsi, un smaphore est un objet possdant deux attributs :

l'un de ces deux attributs doit permettre de comptabiliser le nombre de ressources disponibles un instant
donn ;
l'autre attribut doit contenir le nombre maximal de ressources.

Si on reprend encore une fois l'exemple du restaurant, le smaphore reprsentant le rceptionniste aura un de ses
deux attributs 20 (le nombre maximal de tables dans le restaurant) et l'autre 0 (le nombre de tables disponibles,
c'est--dire aucune). Afin de communiquer avec le smaphore, on dispose de deux procdures, que l'on appelle
communment P et V. Ces deux procdures servent pour l'accs aux ressources : P permet ainsi de demander une
ressource et V permet de librer une ressource. Un moyen mnmotechnique pour s'en rappeler est d'associer P
Prendre une ressource et V Valider une ressource ! Ces deux procdures peuvent tre videmment
nommes selon votre gr, mais ces deux appellations sont les plus rencontres dans la programmation systme.
Dans notre approche objet, ces deux procdures seront incluses en tant que mthodes dans notre objet Smaphore.

III - Programmation sous Delphi

III-A - Dfinition de la classe TSemaphore

Afin d'illustrer les mcanismes des smaphores, nous implmenterons une classe sous Delphi. Cette classe
reprsentera donc un smaphore, avec ses deux attributs :

valeur , pour le nombre de ressources disponibles ;


limite , pour le nombre maximal de ressources.

Nous ajouterons galement les deux procdures P et V, sans oublier une fonction qui, pour notre confort, retournera le
nombre actuel de ressources disponibles. Programmation oriente objet oblige, un constructeur sera dfini pour cette
classe. Enfin, la classe TSemaphore aura un attribut priv supplmentaire, permettant de stocker le Handle retourn
par la fonction CreateSemaphore de l'API Windows. En effet, Windows possde un support pour les smaphores et
les mutex, ce support tant compos, pour chaque type, de trois fonctions.

Tlchargez l'archive de la classe Semaphore (Delphi)

-4-
Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par
les droits d'auteur. Copyright 2013 Mathieu Dalbin. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans
l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts. Cette page est dpose la SACD.
http://mdalbin.developpez.com/tutoriels/general/semaphores/
Smaphores et Mutex en Delphi et Java par Mathieu Dalbin

Voyons prsent la dclaration de la classe TSemaphore :

type
TSemaphore = class(TObject)
private
FValeur: Integer;
FLimite: Integer;
FHSemaphore: Cardinal;
public
constructor Create(Valeur: Integer; Limite: Integer);
procedure P;
procedure V;
function GetValeur: Integer;
destructor Destroy; override;
end;

III-B - Constructeur

Comme on peut le constater, on passe la valeur initiale et la limite du smaphore en paramtre du constructeur.
Voyons la dfinition du constructeur :

constructor TSemaphore.Create(Valeur: Integer; Limite: Integer);


begin
inherited Create;
FValeur := Valeur;
FLimite := Limite;
FHSemaphore := CreateSemaphore(nil, FValeur, FLimite, nil);
if FHSemaphore = 0 then Fail;
end;

On remarque l'utilisation de la fonction CreateSemaphore de l'API de Windows. Cette fonction permet de crer un
smaphore que Windows pourra grer. En effet, les mcanismes de gestion de threads tant internes Windows, il
est impossible de se passer des fonctions ddies pour grer un smaphore. La fonction CreateSemaphore renvoie
un Handle vers le smaphore qui a t cr. On ne se souciera pas dans notre cas du paramtre de scurit (le
premier paramtre de la fonction), en acceptant d'utiliser le niveau de scurit par dfaut, qui est suffisant dans la
plupart des cas. De mme, on vitera ici d'utiliser le quatrime paramtre qui permet de donner un nom au smaphore,
tant donn que le nommage du smaphore n'est utile que dans trs peu de cas. Le nommage d'un smaphore n'aura
d'intrt que si l'on dcide de crer plusieurs instances d'un mme smaphore, au sein du systme d'exploitation, ce
qui est fait l'aide de la fonction OpenSemaphore de l'API Windows.

Les fonctions de l'API de Windows assurent donc une gestion minimale des ressources, mais cette gestion ne remplit
pas toutes nos exigences de programmeur. Il est en effet impossible de connatre le nombre de ressources disponible
un moment donn. Ceci est combl par l'ajout d'attribut dans la classe TSemaphore, que nous avons programme.

Regardons la dfinition de la mthode Free :

destructor TSemaphore.Destroy;
begin
CloseHandle(FHSemaphore);
inherited Destroy;
end;

Cette fonction utilise la fonction CloseHandle afin de librer le smaphore au sein du systme d'exploitation,
lorsque l'on en a plus besoin. Cet appel est ncessaire afin de quitter proprement l'environnement d'excution du
programme !

III-C - Les principales mthodes

Arrtons-nous un instant sur les principales mthodes de l'objet TSemaphore :

-5-
Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par
les droits d'auteur. Copyright 2013 Mathieu Dalbin. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans
l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts. Cette page est dpose la SACD.
http://mdalbin.developpez.com/tutoriels/general/semaphores/
Smaphores et Mutex en Delphi et Java par Mathieu Dalbin

procedure TSemaphore.P;
begin
while FValeur < 1 do
begin
WaitForSingleObject(FHSemaphore, INFINITE);
end;
FValeur := FValeur - 1;
end;

procedure TSemaphore.V;
begin
FValeur := FValeur + 1;
ReleaseSemaphore(FHSemaphore, 1, nil);
end;

function TSemaphore.GetValeur: Integer;


begin
Result := FValeur;
end;

Analysons tout d'abord la mthode P : pour rappel, cette mthode sert prendre une ressource si il y en a au
moins une de disponible. On remarque l'utilisation de la fonction WaitForSingleObject : cette fonction a pour
but d'attendre que le smaphore lui signale qu'une ressource est libre d'accs. On passe alors le handle du
smaphore en paramtre de cette fonction. Si l'on dcortique le droulement de cette mthode P, on observe que
l'on excute la boucle tant qu'il n'y a pas de ressource disponible. Dans ce cas-ci, la boucle s'excute, et l'appel
la fonction WaitForSingleObject fige le thread appelant. Ce thread continuera son excution lorsque'il recevra un
message de la part du smaphore, l'informant qu'une ressource vient de se librer. L'excution de la boucle s'achve
donc, et si un autre thread n'a pas t plus rapide , le thread appelant prend la ressource, en dcrmentant
la valeur de 1. Si un autre thread a prcd ce thread, la boucle est nouveau excute, car nouveau aucune
ressource n'est disponible.

Regardons la mthode V, qui sert librer une ressource. L aussi, nous faisons appel une fonction de l'API de
Windows, ReleaseSemaphore. Cette fonction sert signaler aux threads rests figs qu'une ressource vient
de se librer. L'incrmentation de la valeur du smaphore permet de garder le nombre de ressources disponibles
jour. Enfin la fonction getValeur est un accesseur en lecture sur l'attribut valeur, elle permet de connatre le nombre
de ressources disponibles un moment prcis.

III-D - La synchronisation sous Delphi

La synchronisation sous Delphi est faite grce aux sections critiques. Les sections critiques permettent, dans une
application possdant plusieurs threads, de contrler l'accs des donnes ou du code prcis. Une section critique
agt donc comme un commutateur, au niveau du code : ainsi, un bloc de code protg par une section critique ne
pourra tre excut que par un seul thread la fois. Ceci implique donc que si deux ou plusieurs threads diffrents
tentent d'excuter ce bloc de code, un ordre d'excution sera mis en place afin que chaque thread excute le bloc
de code tour tour. Les sections critiques sont reprsentes travers la classe TCriticalSection, situe dans l'unit
SyncObjs. Cette classe possde deux mthodes qui permettent de dlimiter le bloc de code qui sera excut en
section critique. La premire mthode, Acquire, galement appele Enter, permet de dfinir le point de dpart de la
section critique. La seconde mthode, appele Release ou Leave, dfinit le point d'arrt de la section critique. Voici
un exemple d'utilisation des sections critiques, cet exemple tant issu de la dclaration de la mthode Depose de
la classe TBal, que nous tudierons plus tard :

procedure TBal.Depose(X: Integer);


begin
FSectionCritique.Acquire;
try
FTable[FIndiceDepot] := X;
FIndiceDepot := (FIndiceDepot + 1) mod 10;
finally
FSectionCritique.Release;
end;
end;

-6-
Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par
les droits d'auteur. Copyright 2013 Mathieu Dalbin. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans
l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts. Cette page est dpose la SACD.
http://mdalbin.developpez.com/tutoriels/general/semaphores/
Smaphores et Mutex en Delphi et Java par Mathieu Dalbin

Ainsi tout le code situ entre ces deux mthodes s'excutera en section critique. Une consquence de ce concept
est que les donnes manipules dans ce bloc de code protg ne peuvent tre modifies que par un seul thread
la fois, si videmment elles ne sont pas modifies hors de la section critique par tout autre thread. Dans notre cas,
nous avons souhait protger les attributs privs de la classe TBal, qui sont FIndiceDepot et FIndiceRetrait, car leur
modification par deux ou plusieurs threads simultanment auraient pu conduire des effets de bords dsagrables,
pouvant perturber le droulement normal du programme.

IV - Programmation sous Java

IV-A - La classe Semaphore

Contrairement Delphi, le langage Java prvoit un mcanisme pour grer les smaphores, mais il est cependant
ncessaire d'utiliser le compteur de valeur et la limite de ressources. Les deux attributs valeur et limite sont
donc toujours prsents dans l'implmentation sous Java. Nous retrouvons galement les deux procdures P() et V()
pour la gestion des ressources et la fonction getValeur() qui retourne le nombre de ressources disponibles.

Tlchargez l'archive de la classe Semaphore (Java)

Voici la dfinition de la classe Semaphore :

public class Semaphore


{
private int valeur;
private int limite;

public Semaphore(int valeur, int limite)


{
this.valeur=valeur;
this.limite=limite;
}

public int getValeur()


{
return valeur;
}

synchronized public void P()


{
while (valeur<1)
{
try
{
wait();
}
catch(InterruptedException e)
{
System.out.println("Erreur de Smaphore");
}
}
valeur=valeur-1;
}

synchronized public void V()


{
valeur=valeur+1;
notify();
}
}

-7-
Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par
les droits d'auteur. Copyright 2013 Mathieu Dalbin. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans
l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts. Cette page est dpose la SACD.
http://mdalbin.developpez.com/tutoriels/general/semaphores/
Smaphores et Mutex en Delphi et Java par Mathieu Dalbin

IV-B - La synchronisation sous Java

Nous retrouvons donc les mmes principes que pour la programmation sous Delphi, savoir que la procdure P
met en attente le thread l'appelant avec l'instruction wait(). De la mme faon, la procdure V libre une ressource et
signale aux threads en attente qu'une ressource s'est libre, grce l'instruction notify(). Ces deux mthodes sont
dclares avec la directive synchronized, ce qui leur confre un traitement spcial au niveau de la machine virtuelle :
en effet, le mot cl synchronized est utilis pour signifier que les fonctions affectes ne peuvent pas accder
en mme temps aux objets situs dans l'environnement d'excution. Ces fonctions s'excuteront donc l'une
aprs l'autre si leur appel est simultan. Ceci vite ainsi qu'un objet soit modifi par deux threads simultanment, ce
qui pourrait conduire des effets de bords indsirables.

IV-C - Apparition dans Java 1.5

Depuis la version 1.5 du JRE de Java, une nouvelle classe a t introduite afin de fournir un support plus complet
pour les smaphores. Cette classe Semaphore est situe dans le package java.util.concurrent : vous pouvez obtenir
les spcifications de cette classe sur le site de Sun. Cette nouvelle classe permet donc de crer et de manipuler des
smaphores, sans se proccuper vritablement des compteurs de ressources disponibles, le tout tant gr au sein
de la machine virtuelle. Un article concernant les nouveauts de Java 1.5 est galement disponible.

V - Un exemple concret de Producteurs - Consommateurs

V-A - Principe gnral

Le principe des Producteurs - Consommateurs est bien connu des programmeurs systme, car il revient trs souvent
au niveau d'un systme informatique. Le principe est simple, car il repose sur les relations entre plusieurs threads
et un objet commun, cet objet subissant des modifications de la part des threads. Dans cet exemple, nous prendrons
le cas d'une BAL, une bote Aux Lettres, partage par cinq threads. Nous stockerons dans cette bote aux lettres
des nombres entiers. Nous utiliserons galement deux types de threads : trois threads seront producteurs de
valeurs, leur but sera de remplir la bote aux lettres, et deux threads seront consommateurs, car ils devront lire
les valeurs situes dans la bote.

V-B - La Bote Aux Lettres

Afin de mieux comprend le mcanisme de gestion de la BAL, regardons les dfinitions de la classe TBal en Delphi
et de la classe BAL Java :

type
TBal = class(TObject)
private
FTable: array[0..9] of Integer;
FIndiceDepot: Integer;
FIndiceRetrait: Integer;
FSemaphoreDepot: TSemaphore;
FSemaphoreRetrait: TSemaphore;
FMemo: TMemo;
FSectionCritique: TCriticalSection;
public
constructor Create(Memo: TMemo);
procedure DeposeP();
procedure DeposeV();
procedure RetireP();
procedure RetireV();
procedure Depose(X: Integer);
function Retire: Integer;
procedure Affiche;
procedure Free;
end;

-8-
Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par
les droits d'auteur. Copyright 2013 Mathieu Dalbin. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans
l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts. Cette page est dpose la SACD.
http://mdalbin.developpez.com/tutoriels/general/semaphores/
Smaphores et Mutex en Delphi et Java par Mathieu Dalbin

constructor TBal.Create(Memo: TMemo);


begin
inherited Create;
FMemo := Memo;
FIndiceDepot := 0;
FIndiceRetrait := 0;
FSemaphoreDepot := TSemaphore.Create(10, 10);
FSemaphoreRetrait := TSemaphore.Create(0, 10);
FSectionCritique := TCriticalSection.Create;
end;

procedure TBal.DeposeP();
begin
FSemaphoreDepot.P;
end;

procedure TBal.DeposeV();
begin
FSemaphoreDepot.V;
end;

procedure TBal.RetireP();
begin
FSemaphoreRetrait.P;
end;

procedure TBal.RetireV();
begin
FSemaphoreRetrait.V;
end;

procedure TBal.Depose(X: Integer);


begin
FSectionCritique.Acquire;
try
FTable[FIndiceDepot] := X;
FIndiceDepot := (FIndiceDepot + 1) mod 10;
finally
FSectionCritique.Release;
end;
end;

function TBal.Retire;
begin
FSectionCritique.Acquire;
try
Result := FTable[FIndiceRetrait];
FTable[FIndiceRetrait] := 0;
FIndiceRetrait := (FIndiceRetrait + 1) mod 10;
finally
FSectionCritique.Release;
end;
end;

procedure TBal.Affiche;
var Valeur: string;
var I: Integer;
begin
Valeur := '';
for I := 0 to 9 do Valeur := Valeur + IntToStr(FTable[I]);
Valeur := Valeur + Format(' %d %d', [FSemaphoreDepot.GetValeur, FSemaphoreRetrait.GetValeur]);
FMemo.Lines.Append(Valeur);
end;

procedure TBal.Free;
begin
FSemaphoreDepot.Free;
FSemaphoreRetrait.Free;
FSectionCritique.Free;
inherited Free;
end;

-9-
Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par
les droits d'auteur. Copyright 2013 Mathieu Dalbin. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans
l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts. Cette page est dpose la SACD.
http://mdalbin.developpez.com/tutoriels/general/semaphores/
Smaphores et Mutex en Delphi et Java par Mathieu Dalbin

public class BAL


{
private int[] table;
private int indiceDepot,indiceRetrait;
private Semaphore semaphoreDepot,semaphoreRetrait;

public BAL()
{
table=new int[10];
indiceDepot=0;
indiceRetrait=0;
semaphoreDepot=new Semaphore(10,10);
semaphoreRetrait=new Semaphore(0,10);
}

public void deposeP() { semaphoreDepot.P(); }


public void deposeV() { semaphoreDepot.V(); }
public void retireP() { semaphoreRetrait.P(); }
public void retireV() { semaphoreRetrait.V(); }

synchronized public void depose(int x)


{
table[indiceDepot]=x;
indiceDepot=(indiceDepot+1)%10;
}

synchronized public int retire()


{
int val;
val=table[indiceRetrait];
table[indiceRetrait]=0;
indiceRetrait=(indiceRetrait+1)%10;
return val;
}

public void affiche()


{
for (int i=0;i<9;i++)
{
System.out.print(""+table[i]+" ");
}
System.out.print(" "+semaphoreDepot.getValeur()+" "+semaphoreRetrait.getValeur());
System.out.println();
}
}

Tlchargez l'archive de la classe TBal (Delphi)

Tlchargez l'archive de la classe BAL (Java)

Afin de garder une certaine uniformit, les deux codes se ressemblent fortement, tout en respectant les contraintes de
chaque langage. On peut ainsi voir que les classes TBal en Delphi et BAL en Java se composent deux cinq attributs :

un tableau de 10 cases ;
un indice de dpt ;
un indice de retrait ;
un smaphore pour le retrait ;
un smaphore pour le dpt.

On trouve galement six mthodes importantes : quatre servent dialoguer avec les smaphores, et les
deux autres servent dposer ou retirer une valeur de la bote. Une autre classification serait de dire que trois
mthodes concernent le dpt et les trois autres sont utilises pour le retrait.

- 10 -
Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par
les droits d'auteur. Copyright 2013 Mathieu Dalbin. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans
l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts. Cette page est dpose la SACD.
http://mdalbin.developpez.com/tutoriels/general/semaphores/
Smaphores et Mutex en Delphi et Java par Mathieu Dalbin

V-C - Les Producteurs et les Consommateurs

Analysons maintenant les dfinitions des producteurs et des consommateurs :

Dfinitions des producteurs en Delphi et Java :

type
TProducteur = class(TThread)
private
FBal: TBal;
FNom: string;
protected
procedure Execute; override;
public
constructor Create(Bal: TBal; Nom: string);
end;

constructor TProducteur.Create(Bal: TBal; Nom: string);


begin
inherited Create(false);
FBal := Bal;
FNom := Nom;
end;

procedure TProducteur.Execute;
var I, Valeur: Integer;
begin
for I := 1 to 4 do
begin
Sleep(random(10) * 1000);
Valeur := random(9) + 1;
FBal.DeposeP();
FBal.Depose(Valeur);
FBal.RetireV();
FBal.Affiche;
end;
end;

public class Producteur extends Thread


{
private BAL bal;
private String nom;

public Producteur(BAL bal,String nom)


{
this.bal=bal;
this.nom=nom;
start();
}

public void run()


{
int valeur;
for (int i=1;i<=4;i++)
{
try
{
sleep((int) (Math.random()*10000));
}
catch (InterruptedException e) { }
valeur=(int) (Math.random()*10);
bal.deposeP();
bal.depose(valeur);
bal.retireV();
bal.affiche();
}
}
}

- 11 -
Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par
les droits d'auteur. Copyright 2013 Mathieu Dalbin. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans
l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts. Cette page est dpose la SACD.
http://mdalbin.developpez.com/tutoriels/general/semaphores/
Smaphores et Mutex en Delphi et Java par Mathieu Dalbin

Tlchargez l'archive de la classe Producteurs (Delphi)

Tlchargez l'archive de la classe Producteurs (Java)

Dfinitions des consommateurs en Delphi et Java :

type
TConsommateur = class(TThread)
private
FBal: TBal;
FNom: string;
protected
procedure Execute; override;
public
constructor Create(Bal: TBal; Nom: string);
end;

constructor TConsommateur.Create(Bal: TBal; Nom: string);


begin
inherited Create(false);
FBal := Bal;
FNom := Nom;
end;

procedure TConsommateur.Execute;
var I, Valeur: Integer;
begin
for I := 1 to 6 do
begin
Sleep(random(10) * 1000);
FBal.RetireP();
Valeur := FBal.Retire;
FBal.DeposeV();
FBal.Affiche;
end;
end;

public class Consommateur extends Thread


{
private BAL bal;
private String nom;

public Consommateur(BAL bal,String nom)


{
this.bal=bal;
this.nom=nom;
start();
}

public void run()


{
int valeur;
for (int i=1;i<=6;i++)
{
try
{
sleep((int) (Math.random()*10000));
}
catch (InterruptedException e) { }
bal.retireP();
valeur=bal.retire();
bal.deposeV();
bal.affiche();
}
}
}

- 12 -
Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par
les droits d'auteur. Copyright 2013 Mathieu Dalbin. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans
l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts. Cette page est dpose la SACD.
http://mdalbin.developpez.com/tutoriels/general/semaphores/
Smaphores et Mutex en Delphi et Java par Mathieu Dalbin

Tlchargez l'archive de la classe Consommateurs (Delphi)

Tlchargez l'archive de la classe Consommateurs (Java)

Ces deux objets sont des descendants des classes threads disponibles pour les deux langages (nous
admettrons que vous connaissez un minimum la programmation des threads pour le langage qui vous intresse).
Intressons-nous tout d'abord aux producteurs : la mthode principale du thread (Execute en Delphi et Run en java)
contient trois appels de mthodes de la BAL. La premire mthode appele est deposeP : son but est de prendre une
ressource de dpt s'il y en a au moins une de disponible, ou de mettre en attente le thread appelant. La mthode
suivante, depose, permet de dposer une valeur gnre au hasard dans la BAL, et enfin la troisime mthode retireV
libre une ressource de retrait. De faon similaire, la boucle principale des consommateurs fait appel trois mthodes
de la BAL : retireP qui doit prendre une ressource de retrait, retire qui retire une valeur de la BAL et deposeV qui
libre une ressource de dpt. C'est encore obscur ? Ne vous inquitez pas, nous allons analyser tout ceci en dtail !

V-D - Initialisation du mcanisme

Tout d'abord, revenons l'objet BAL et son initialisation (il est important de garder toujours en tte le nombre
de ressources disponibles pour bien saisir le droulement du programme). Il existe 10 cases dans la BAL, chacune
de ses cases pouvant contenir un nombre entier. Le nombre maximal de ressources pour les smaphores de dpt
et de retrait est donc de 10 : dans les deux cas, on ne pourra au maximum dposer que 10 valeurs et on ne pourra
en lire que 10 ! Seulement au dbut de l'excution, si on admet que la BAL est vide, il y a 10 cases pour crire mais
0 pour lire, car il n'y a rien lire.

C'est ce niveau que l'initialisation correcte des smaphores joue un rle important : en
effet, pour le smaphore de dpt, il y a donc 10 ressources maximales et 10 ressources
disponibles, car on peut crire dans les 10 cases du tableau, mais pour le smaphore
de retrait, il y a bien 10 ressources maximales mais 0 ressource disponible, car il
n'y a rien lire.

Dans les diffrents codes ci-dessus, on constate que les smaphores ont t initialiss ainsi.

V-E - Droulement du programme

Nous pouvons dbuter l'excution du programme : les threads sont crs et lancs automatiquement, tous en
mme temps . Comme nous l'avons vu prcdemment, tous les threads commencent par essayer de prendre
une ressource, soit une ressource de dpt, soit une ressource de retrait, en interrogeant le smaphore
correspondant sur le nombre de ressource disponible. En ralit, chaque thread fait un appel la mthode P du
smaphore concern, il demande donc, quoi qu'il arrive, une ressource, mais s'il n'y a pas de ressource disponible,
le smaphore le met en attente. Il n'est pas vident que tous les threads obtiennent effectivement une ressource,
et dans ce cas, les threads concerns se verront temporairement figs par le systme. Observons le comportement
d'un thread consommateur : sa premire action est d'appeler retireP, qui permet de prendre une ressource de retrait.
Seulement au tout dbut de l'excution, aucun ressource de retrait n'est disponible, car personne n'a encore
crit dans la BAL.

La consquence de cet appel est donc une mise en attente du thread consommateur
appelant : ainsi au dbut de l'excution, les deux threads consommateurs attendent
qu'une valeur soit crite dans la BAL.

Pour un thread producteur, le droulement est inverse : comme la BAL est vide, 10 ressources sont disponibles,
donc le thread appelant deposeP obtient l'autorisation de dposer une valeur dans la BAL. Aprs le dpt
d'une valeur, l'appel retireV permet de signifier aux threads consommateurs qu'une ressource de retrait est
disponible.

- 13 -
Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par
les droits d'auteur. Copyright 2013 Mathieu Dalbin. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans
l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts. Cette page est dpose la SACD.
http://mdalbin.developpez.com/tutoriels/general/semaphores/
Smaphores et Mutex en Delphi et Java par Mathieu Dalbin

Ainsi un des deux threads consommateurs, qui avaient prcdemment t figs,


continue son excution et retire une valeur de la BAL.

Aprs avoir retir cette valeur, il signifie aux threads producteurs qu'une case vient de se librer et qu'elle est
de nouveau disponible pour une criture. Ce droulement se prolonge jusqu' ce que tous les threads producteurs
aient crit leurs valeurs dans la BAL et que tous les threads consommateurs aient lu les valeurs stockes (dans notre
cas, le nombre total de valeur est de 12, un thread producteur crivant 4 valeurs chacun et un thread consommateur
en lisant 6).

la fin de l'excution, les producteurs et les consommateurs ayant fait tout leur travail, la BAL est nouveau vide.

V-F - Programmes d'exemple

Les programmes disponibles en tlchargements, pour Delphi et Java, illustrent ce phnomne : pour la bonne
comprhension du systme, nous avons employs des temporisateurs afin que l'excution ne soit pas trop rapide.
Les temporisateurs modifient lgrement le comportement des smaphores, car on perd sensiblement la notion
de synchronisation, mais cette utilisation est ncessaire pour montrer le mcanisme de gestion des smaphores.
Lors de l'excution de ces programmes, vous pourrez constater que l'tat de la BAL, ainsi que la valeur de chaque
smaphore, est affiche soit dans une fentre ddie sous Delphi, soit dans la console sous Java (la version Delphi
a t compile avec Delphi 7, et la version Java a t test avec succs sous Eclipse, avec un JRE version 1.4.2).

Tlchargez l'archive Producteurs Consommateurs (Delphi)

Tlchargez l'archive Producteurs Consommateurs (Java)

VI - Conclusion

Vous avez donc toutes les cartes en main pour matriser la synchronisation de thread sous Delphi et Java. Pour en
savoir plus sur les threads sous Delphi, vous pouvez consulter ce tutoriel. Il existe galement un tutoriel sous Delphi
pour l'excution de tches priodiques en arrire plan. Pour Java, vous pouvez consulter ce cours.

Pour tous commentaires, suggestions, ides ou critiques, vous pouvez me contacter par MP ou sur les forums de
Developpez.com.

- 14 -
Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par
les droits d'auteur. Copyright 2013 Mathieu Dalbin. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans
l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts. Cette page est dpose la SACD.
http://mdalbin.developpez.com/tutoriels/general/semaphores/

Vous aimerez peut-être aussi