Код: Выделить всё
init(int n) // initialize with n permits
boolean acquire() // try to acquire a permit, returning true if succeeded (non-blocking)
void forceAcquire() // acquire a permit even when none are free, potentially making the number of available permits negative
void release() // increase the amount of available permits
< /code>
Дополнительные требования: < /p>
[list]
[*] Все операции являются атомными (например, обычный семафор) < /li>
acquire[*] Синхронизация должна работать в нескольких службах/узлах, поэтому я должен интегрироваться с чем -то вроде Redis
[/list]
Я использую Spring Boot 3 с Java 17. />
Я думаю, что может быть возможно достичь того же результата с ручным отслеживанием переполнения с использованием chatomiclong: < /p>
class OverflowableSemaphore {
RSemaphore semaphore;
RAtomicLong overflowCounter;
public OverflowableSemaphore(int n) {
this.semaphore.trySetPermits(n);
}
public boolean acquire() {
return semaphore.tryAcquire();
}
public void forceAcquire() {
boolean acquired = acquire();
if (acquired) {
return;
}
else {
overflowCounter.incrementAndGet();
}
}
public void release() {
while (true) {
long currentOverflow = overflowCounter.get();
if (currentOverflow > 0) {
if (overflowCounter.compareAndSet(currentOverflow, currentOverflow - 1)) {
return;
}
// else: retry due to race
}
else {
semaphore.release();
return;
}
}
}
}
< /code>
Однако это кажется довольно неэффективным, поскольку он потенциально требует многих обратных вызовов для Redis.
Кроме того, я хотел бы избежать пользовательских реализаций, если это вообще возможно, и предпочитаю что -то более хорошо протестированное.>
Подробнее здесь: https://stackoverflow.com/questions/796 ... is-reached