Java Thread - Exemple de Mutex et de sémaphore
Exemple Java multi threads pour vous montrer comment utiliserSemaphore
etMutex
pour limiter le nombre de threads pour accéder aux ressources.
-
Semaphores
- Restreint le nombre de threads pouvant accéder à une ressource. Exemple, limitez 10 connexions maximum pour accéder simultanément à un fichier. -
Mutex
- Un seul thread pour accéder à une ressource à la fois. Par exemple, lorsqu'un client accède à un fichier, personne d'autre ne doit avoir accès au même fichier en même temps.
1. Sémaphore
Considérons une cabine ATM avec 4 distributeurs automatiques,Semaphore
peut s'assurer que seulement 4 personnes peuvent accéder simultanément.
SemaphoreTest.java
package com.techfou; import java.util.concurrent.Semaphore; public class SemaphoreTest { // max 4 people static Semaphore semaphore = new Semaphore(4); static class MyATMThread extends Thread { String name = ""; MyATMThread(String name) { this.name = name; } public void run() { try { System.out.println(name + " : acquiring lock..."); System.out.println(name + " : available Semaphore permits now: " + semaphore.availablePermits()); semaphore.acquire(); System.out.println(name + " : got the permit!"); try { for (int i = 1; i <= 5; i++) { System.out.println(name + " : is performing operation " + i + ", available Semaphore permits : " + semaphore.availablePermits()); // sleep 1 second Thread.sleep(1000); } } finally { // calling release() after a successful acquire() System.out.println(name + " : releasing lock..."); semaphore.release(); System.out.println(name + " : available Semaphore permits now: " + semaphore.availablePermits()); } } catch (InterruptedException e) { e.printStackTrace(); } } } public static void main(String[] args) { System.out.println("Total available Semaphore permits : " + semaphore.availablePermits()); MyATMThread t1 = new MyATMThread("A"); t1.start(); MyATMThread t2 = new MyATMThread("B"); t2.start(); MyATMThread t3 = new MyATMThread("C"); t3.start(); MyATMThread t4 = new MyATMThread("D"); t4.start(); MyATMThread t5 = new MyATMThread("E"); t5.start(); MyATMThread t6 = new MyATMThread("F"); t6.start(); } }
La sortie peut varier, mais le flux de verrouillage et de libération doit être plus ou moins le même.
Total available Semaphore permits : 4 A : acquiring lock... D : acquiring lock... C : acquiring lock... B : acquiring lock... B : available Semaphore permits now: 4 C : available Semaphore permits now: 4 E : acquiring lock... F : acquiring lock... F : available Semaphore permits now: 2 F : got the permit! F : is performing operation 1, available Semaphore permits : 1 D : available Semaphore permits now: 4 A : available Semaphore permits now: 4 D : got the permit! D : is performing operation 1, available Semaphore permits : 0 E : available Semaphore permits now: 2 C : got the permit! B : got the permit! C : is performing operation 1, available Semaphore permits : 0 B : is performing operation 1, available Semaphore permits : 0 F : is performing operation 2, available Semaphore permits : 0 D : is performing operation 2, available Semaphore permits : 0 C : is performing operation 2, available Semaphore permits : 0 B : is performing operation 2, available Semaphore permits : 0 F : is performing operation 3, available Semaphore permits : 0 D : is performing operation 3, available Semaphore permits : 0 C : is performing operation 3, available Semaphore permits : 0 B : is performing operation 3, available Semaphore permits : 0 F : is performing operation 4, available Semaphore permits : 0 D : is performing operation 4, available Semaphore permits : 0 C : is performing operation 4, available Semaphore permits : 0 B : is performing operation 4, available Semaphore permits : 0 D : is performing operation 5, available Semaphore permits : 0 F : is performing operation 5, available Semaphore permits : 0 B : is performing operation 5, available Semaphore permits : 0 C : is performing operation 5, available Semaphore permits : 0 D : releasing lock... F : releasing lock... D : available Semaphore permits now: 1 A : got the permit! A : is performing operation 1, available Semaphore permits : 0 F : available Semaphore permits now: 1 E : got the permit! E : is performing operation 1, available Semaphore permits : 0 B : releasing lock... B : available Semaphore permits now: 1 C : releasing lock... C : available Semaphore permits now: 2 A : is performing operation 2, available Semaphore permits : 2 E : is performing operation 2, available Semaphore permits : 2 A : is performing operation 3, available Semaphore permits : 2 E : is performing operation 3, available Semaphore permits : 2 A : is performing operation 4, available Semaphore permits : 2 E : is performing operation 4, available Semaphore permits : 2 A : is performing operation 5, available Semaphore permits : 2 E : is performing operation 5, available Semaphore permits : 2 A : releasing lock... A : available Semaphore permits now: 3 E : releasing lock... E : available Semaphore permits now: 4
Observez attentivement la sortie ci-dessus, vous verrez qu'il y a maximum 4 personnes (C, B, F, D) pour effectuer une opération à la fois, les personnes A et E sont en attente. Dès que l'un d'eux libère le verrou (D et F), A et E l'acquièrent et le reprennent immédiatement.
2. Mutex
Mutex
est leSemaphore
avec un nombre d'accès de 1. Considérez une situation d'utilisation de casiers à la banque. Habituellement, la règle est qu'une seule personne est autorisée à entrer dans les vestiaires.
MutexTest.java
package com.techfou; import java.util.concurrent.Semaphore; public class SemaphoreTest { // max 1 people static Semaphore semaphore = new Semaphore(1); static class MyLockerThread extends Thread { String name = ""; MyLockerThread(String name) { this.name = name; } public void run() { try { System.out.println(name + " : acquiring lock..."); System.out.println(name + " : available Semaphore permits now: " + semaphore.availablePermits()); semaphore.acquire(); System.out.println(name + " : got the permit!"); try { for (int i = 1; i <= 5; i++) { System.out.println(name + " : is performing operation " + i + ", available Semaphore permits : " + semaphore.availablePermits()); // sleep 1 second Thread.sleep(1000); } } finally { // calling release() after a successful acquire() System.out.println(name + " : releasing lock..."); semaphore.release(); System.out.println(name + " : available Semaphore permits now: " + semaphore.availablePermits()); } } catch (InterruptedException e) { e.printStackTrace(); } } } public static void main(String[] args) { System.out.println("Total available Semaphore permits : " + semaphore.availablePermits()); MyLockerThread t1 = new MyLockerThread("A"); t1.start(); MyLockerThread t2 = new MyLockerThread("B"); t2.start(); MyLockerThread t3 = new MyLockerThread("C"); t3.start(); MyLockerThread t4 = new MyLockerThread("D"); t4.start(); MyLockerThread t5 = new MyLockerThread("E"); t5.start(); MyLockerThread t6 = new MyLockerThread("F"); t6.start(); } }
La sortie peut varier, mais le flux de verrouillage et de libération doit être le même.
Total available Semaphore permits : 1 A : acquiring lock... B : acquiring lock... A : available Semaphore permits now: 1 C : acquiring lock... B : available Semaphore permits now: 1 C : available Semaphore permits now: 0 A : got the permit! D : acquiring lock... E : acquiring lock... A : is performing operation 1, available Semaphore permits : 0 E : available Semaphore permits now: 0 D : available Semaphore permits now: 0 F : acquiring lock... F : available Semaphore permits now: 0 A : is performing operation 2, available Semaphore permits : 0 A : is performing operation 3, available Semaphore permits : 0 A : is performing operation 4, available Semaphore permits : 0 A : is performing operation 5, available Semaphore permits : 0 A : releasing lock... A : available Semaphore permits now: 1 B : got the permit! B : is performing operation 1, available Semaphore permits : 0 B : is performing operation 2, available Semaphore permits : 0 B : is performing operation 3, available Semaphore permits : 0 B : is performing operation 4, available Semaphore permits : 0 B : is performing operation 5, available Semaphore permits : 0 B : releasing lock... B : available Semaphore permits now: 1 C : got the permit! C : is performing operation 1, available Semaphore permits : 0 C : is performing operation 2, available Semaphore permits : 0 C : is performing operation 3, available Semaphore permits : 0 C : is performing operation 4, available Semaphore permits : 0 C : is performing operation 5, available Semaphore permits : 0 C : releasing lock... C : available Semaphore permits now: 1 E : got the permit! E : is performing operation 1, available Semaphore permits : 0 E : is performing operation 2, available Semaphore permits : 0 E : is performing operation 3, available Semaphore permits : 0 E : is performing operation 4, available Semaphore permits : 0 E : is performing operation 5, available Semaphore permits : 0 E : releasing lock... E : available Semaphore permits now: 1 D : got the permit! D : is performing operation 1, available Semaphore permits : 0 D : is performing operation 2, available Semaphore permits : 0 D : is performing operation 3, available Semaphore permits : 0 D : is performing operation 4, available Semaphore permits : 0 D : is performing operation 5, available Semaphore permits : 0 D : releasing lock... D : available Semaphore permits now: 1 F : got the permit! F : is performing operation 1, available Semaphore permits : 0 F : is performing operation 2, available Semaphore permits : 0 F : is performing operation 3, available Semaphore permits : 0 F : is performing operation 4, available Semaphore permits : 0 F : is performing operation 5, available Semaphore permits : 0 F : releasing lock... F : available Semaphore permits now: 1
Comme on peut le voir, un seul thread s'exécute à la fois ici. C'est le rôle d'un Mutex.