Nehmen wir an, es gibt eine Karte:
Code: Select all
// key->number of resources occupied
Map map = new ConcurrentHashMap();
- Mehrere Aufgaben werden in verschiedenen Threads ausgeführt.
- Jede Aufgabe prüft vor der Ausführung, ob Ressourcen verfügbar sind. Wenn nicht, wartet es, bis sie von einer anderen Task freigegeben werden, andernfalls aktualisiert es den Zähler und nimmt sich so vorübergehend die benötigten Ressourcen. Dieses Codefragment muss atomar ausgeführt werden.
- Nach den notwendigen Berechnungen „gibt“ die Aufgabe die Ressourcen frei und dekrementiert den Zähler.
Code: Select all
private void do(long key, int count) {
// must be atomic code
while (map.get(key) + count > 25) {
sleep(100);
}
map.put(key, map.get(key) + count);
// must be atomic code
// do some computations
// atomic analog of map.put(key, map.get(key) - count);
map.merge(key, count, (current, next) -> current - next);
}
Beispiel für Code:
Code: Select all
map.merge(key, count, (current, next) -> {
while (current + next > 25) {
sleep(100);
current = map.get(key);
}
return current + next;
}
);
Ich habe die Semaphore-Klasse ausprobiert. Bitte kommentieren Sie, ob ich es richtig verwende?
Code: Select all
Map map = new ConcurrentHashMap();
private void do(long key, int count) {
Semaphore semaphore = map.computeIfAbsent(key, s -> new Semaphore(5));
semaphore.acquire(count);
try {
// do some computations
semaphore.release(count);
} finally {
semaphore.release(intervals.size());
}
}