Cette démonsrtation utilise deux threads synchronisés pour produire une séquence alternée de nombres (1 à 26) et de lettres (A à Z). Chaque thread contrôle l'exécution de l'autre via des mécanismes de synchronisation.
Implémentation C# avec AutoResetEvent
using System;
using System.Threading;
class SequencePrinter
{
private readonly AutoResetEvent _currentLock;
private readonly AutoResetEvent _nextLock;
private readonly int _iterations;
private readonly bool _isNumberPrinter;
public SequencePrinter(AutoResetEvent currentLock, AutoResetEvent nextLock, int iterations, bool isNumberPrinter)
{
_currentLock = currentLock;
_nextLock = nextLock;
_iterations = iterations;
_isNumberPrinter = isNumberPrinter;
}
public void Execute()
{
for (int i = 0; i < _iterations; i++)
{
_currentLock.WaitOne();
if (_isNumberPrinter)
Console.Write(i + 1);
else
Console.Write((char)('A' + i));
_nextLock.Set();
}
}
}
class Orchestrator
{
static void Main()
{
using AutoResetEvent numberLock = new AutoResetEvent(false);
using AutoResetEvent letterLock = new AutoResetEvent(false);
SequencePrinter numberPrinter = new SequencePrinter(
numberLock, letterLock, 26, true);
SequencePrinter letterPrinter = new SequencePrinter(
letterLock, numberLock, 26, false);
Thread numberThread = new Thread(numberPrinter.Execute);
Thread letterThread = new Thread(letterPrinter.Execute);
numberThread.Start();
letterThread.Start();
numberLock.Set();
numberThread.Join();
letterThread.Join();
}
}
Le mécanisme utilise deux verrous AutoResetEvent pour contrôler l'alternance. Le thread numérique démarre en premier grâce au signal initial. Chaque itération libère le verrou du thread suivant après impression.
Implémentation Java avec Semaphore
import java.util.concurrent.Semaphore;
class SequenceGenerator implements Runnable {
private final Semaphore _currentToken;
private final Semaphore _nextToken;
private final int _count;
private final boolean _isDigitGenerator;
public SequenceGenerator(Semaphore currentToken, Semaphore nextToken, int count, boolean isDigitGenerator) {
_currentToken = currentToken;
_nextToken = nextToken;
_count = count;
_isDigitGenerator = isDigitGenerator;
}
public void run() {
for (int index = 0; index < _count; index++) {
try {
_currentToken.acquire();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
if (_isDigitGenerator) {
System.out.print(index + 1);
} else {
System.out.print((char) ('A' + index));
}
_nextToken.release();
}
}
}
public class CoordinationExample {
public static void main(String[] args) throws InterruptedException {
Semaphore digitToken = new Semaphore(1);
Semaphore letterToken = new Semaphore(0);
Thread digitThread = new Thread(new SequenceGenerator(
digitToken, letterToken, 26, true));
Thread letterThread = new Thread(new SequenceGenerator(
letterToken, digitToken, 26, false));
digitThread.start();
letterThread.start();
digitThread.join();
letterThread.join();
}
}
Cette version utilise des sémaphores pour gérer les tours d'exécution. Le sémaphore initial est configuré pour premettre au thread numérique de démarrer en premier. Chaque release() transfère le contrôle à l'autre thread.