-> ce sont des ressources critiques
-> Problème: l’exécution simultané des tâches A et B peut perturber les calculs
Tâche A: dépot de chèque
courA <- Solde
courA + mtCh
Solde <- courA
Tâche B: dépot d'espèces
courB <- Solde
courB + mtL
Solde <- courB
| Solde = X | courA | courB | ||
|---|---|---|---|---|
| X | ||||
| courA -< Solde | X | |||
| courB <- Solde | X | |||
| courB <- courB + mtL | X + mtL | |||
| X+mtL | Solde <- courB | |||
| courA <- courB +mtCh | X+mtCh | |||
| X+mtCh | Solde <- courA |
in et mémorise 7 dans place_libre_suivantein qui vaut toujours 7 et place le nom de son fichier à la séptième position du répértoire puis met à jour in à 8place_libre_suivante, y trouve 7, place le nom du fichier à imprimer à la position 7. Puis met 8 dans in.
Début
Section non critique
/prologue/
*SC*
/épilogue/
Section non critique
Fin
load et un store sont exécutés en concurrence, le load obtiendra soit l'ancienne valeur soit la nouvelle valeur, mais pas une valeur intermédiaire.Nous décrivons seulement un processus Pᵢ typique dont la structure générale est:
while(true){
section_entree();
region_critique();
section_sortie();
hors_region_critique();
}
Les processus P₀ et P₁ partage une variable turn qui indique le tour du processus qui peut entrer en SC. Si turn vaut i, alors Pᵢ peut entrer en SC.
while(true){
while (turn != i); // attente active
region_critique();
turn = j;
hors_region_critique();
}
turn vaut j, Pᵢ ne peut pas entrer en SC.
Pour remédier au problème, nous pouvons remplacer la variable turn par un tableau de variables flag.
var flag = array[0..1] of boolean;
flag[i] indique le désir d'entrer en SC. Si flag[i] vaut true, alors Pᵢ désire entrer en SC. while(true){
flag[i] = true;
while (flag[j]);
region_critique();
flag[i] = false;
hors_region_critique();
}
Une combinaison des 2 algos précédents.
flag et turn.flag indique le désir d'entrer en SCturn indique le tour du processus qui peut entrer en SC. while(true){
flag[i] = true;
turn = j;
while ((flag[j]) && (turn == j));
region_critique();
turn = j;
flag[i] = false;
hors_region_critique();
}
Test_and_Set(TAS)
function TAS(occupée:boolean) -> boolean {
boolean tas
tas <- occupée
occupée <- true
return tas
}
Exemple d'utilisation
while (TAS(C));
region_critique();
C = 0;
hors_region_critique();
Les processus en attente sont mis en file d'attente.
-> utilisation de verrous et de sémaphores
Classe Verrou {
privé ouvert: booléan;
privé attente: liste de tâches;
public void init(){
ouvert = true;
attente = [];
}
public void verrouiller(){
if (ouvert){
ouvert = false;
} else {
attente.ajouter(tâche_courante);
tâche_courante.suspendre();
}
}
public void deverrouiller(){
if (attente.est_vide()){
ouvert = true;
} else {
tâche = attente.retirer();
tâche.reveiller();
}
}
}
Tâche TrainGauche(voie: verrou){
rouler();
voie.verrouiller();
traverser();
voie.deverrouiller();
rouler();
}
Tâche TrainDroite(voie: verrou){
rouler();
voie.verrouiller();
traverser();
voie.deverrouiller();
rouler();
}
Classe Semaphore {
privé jetons: entier;
privé attente: liste de tâches;
public void init(jetons: entier){
jetons = jetons;
attente = [];
}
public void acquire(){
jetons--;
if (jetons < 0){
attente.ajouter(tâche_courante);
tâche_courante.suspendre();
}
}
public void release(){
jetons++;
if (jetons <= 0){
tâche = attente.retirer();
tâche.reveiller();
}
}
}
Tâche TrainGauche(voie: Semaphore){
rouler();
voie.acquire();
traverser();
voie.release();
rouler();
}
Tâche TrainDroite(voie: Semaphore){
rouler();
voie.acquire();
traverser();
voie.release();
rouler();
}
Interblocage: exemple avec des sémaphores
Semaphore S1(1);
Semaphore S2(1);
Tâche A(){
S1.acquire(); // A1
S2.acquire(); // A2
S1.release();
S2.release();
}
Tâche B(){
S2.acquire(); // B1
S1.acquire(); // B2
S2.release();
S1.release();
}