Sorry, ma faute
Tu as bien compris, mais cette doc ne va pas assez loin. Il y a moyen de faire comme tu dis avec un synchronized(myObject).
Je t'ai fait une petite démo à la volée pour me faire pardonner. J'espère que je ne me plante pas trop...
L'équivalent de ta classe A :
Code :
- public class Sync {
- private static Object monitor = new Object();
- public static void foo () {
- System.out.println("About to acquire lock: " + Thread.currentThread().getName());
- synchronized (monitor) {
- System.out.println("Entered critical section: " + Thread.currentThread().getName());
- try {
- Thread.sleep(1);
- }
- catch (InterruptedException e) {
- //
- }
- System.out.println("Exit critical section: " + Thread.currentThread().getName());
- }
- }
- }
|
Remarque le private static Object semaphore = new Object(); : il n'existera dans la demo qu'une seule instance de cet object. Attention, le fait de la déclarer static ne suffit pas à le rendre unique, mais c'est une autre histoire. Ici, on s'assure qu'il est bien unique.
Ensuite, plutôt que de rendre synchronized toute une méthode, je ne sérialise que l'accès à un bout de code à l'aide de synchronized (semaphore).
Pour faire simple, un sémaphore est un flag utilisé pour synchroniser des threads. Il est représenté par l'objet du même nom.
Ensuite, pour attaquer le morceau, ta classe B et ta classe C (désolé, chez moi, c'est A et B ).
Code :
- public class A extends Thread {
- public void run () {
- while (true) {
- Sync.foo();
- try {
- Thread.sleep(1);
- }
- catch (InterruptedException e) {
- //
- }
- }
- }
- }
|
Idem pour B, mutatis mutandis.
Et de quoi tester :
Code :
- public class ConcurrentTest {
- public static void main(String[] args) {
- A a1 = new A();
- A a2 = new A();
- B b1 = new B();
- a1.setName("A1" );
- a2.setName("A2" );
- b1.setName("B1" );
- a1.start();
- a2.start();
- b1.start();
- }
- }
|
Ce qu'il en sort :
About to acquire lock: A1
Entered critical section: A1
About to acquire lock: A2
About to acquire lock: B1
Exit critical section: A1
Entered critical section: A2
Exit critical section: A2
Entered critical section: B1
About to acquire lock: A1
About to acquire lock: A2
Exit critical section: B1
Entered critical section: A1
About to acquire lock: B1
Exit critical section: A1
Entered critical section: A2
Exit critical section: A2
Entered critical section: B1
About to acquire lock: A1
About to acquire lock: A2
Exit critical section: B1
Entered critical section: A1
Exit critical section: A1
Entered critical section: A2
About to acquire lock: B1
About to acquire lock: A1
Exit critical section: A2
Entered critical section: B1
Exit critical section: B1
Entered critical section: A1
About to acquire lock: A2
About to acquire lock: B1
Exit critical section: A1
Entered critical section: A2
About to acquire lock: A1
Exit critical section: A2
On constate que ça se bouscule au portillon, mais qu'il n'y a jamais qu'un seul thread (A1, A2 ou A3) à l'intérieur de la bête à un moment donné.
Tu peux mettre un plus long sleep dans Sync.foo, et tu verras que les autres threads attendent sagement dehors.
Ca s'appelle sérialiser l'accès à une section critique ou qq ch comme ça.
N.B. Tu n'es pas obligé de travailler avec des static sur Sync comme je l'ai fait par facilité. Tu peux très bien instancier Sync une seule fois dans ConcurrentTest et le passer en paramètre à A et B.
---------------
Now Playing: {SYNTAX ERROR AT LINE 1210}