javaredissemaphoreredisson

Redis-backed semaphore with overflow (force acquire even when limit is reached)


I am looking for a semaphore-like construct with the ability to "force" an acquisition, even when maximum capacity is reached, essentially overflowing the semaphore.
I am imagining an interface similar to this:

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 

Additional requirements:

I am using Spring Boot 3 with Java 17.

I have looked at Redisson's RSemaphore, which doesn't support "overflow".
I think it may be possible to achieve the same result with manual tracking of overflow using RAtomicLong:

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;
            }
        }
    }
}

However, this seems quite inefficient as it potentially requires many back and forth calls to Redis.
Additionally, I would like to avoid custom implementations if at all possible, and prefer something more well tested.

Is there an existing solution to this problem?
And if not, how can I improve my proposed solution?


Solution

  • this seems quite inefficient as it potentially requires many back and forth calls to Redis.

    That's probably going to be a property of any Redis-based approach to your particular problem. I expect that you already have it in RSemaphore alone, though of course you have it worse if you add more stuff on top.

    Is there an existing solution to this problem?

    It sounds like you're asking for a library recommendation. That's off-topic here. For the record, however, what you ask for is pretty unusual, even without making it distributed as you want to do, so I would be surprised if you could find it already built.

    how can I improve my proposed solution?

    It is awkward to implement your OverflowableSemaphore in terms of an ordinary (sort of) counting semaphore. I would recommend building yours on top of more primitive objects. In particular,