Java concurrency: lightweight non-blocking semaphore?

I have a situation where I have a callback that I want to execute once. For the argument, we can say that it looks like this:

final X once = new X(1);
Runnable r = new Runnable() {
    @Override public void run() {
        if (once.use())
           doSomething();
    }
}

where X is some parallel object with the following behavior:

  • constructor: X (int N) - allocates N permissions to use

  • boolean use(): If there is at least one permission to use, use one of them and return true. Otherwise, return false. This operation is atomic with respect to several streams.

I know that I can use java.util.concurrent.Semaphore for this, but I do not need its blocking / waiting aspect, and I want this to be a one-time use.

AtomicInteger does not look enough unless I do something like

class NTimeUse {
   final private AtomicInteger count;
   public NTimeUse(int N) { this.count = new AtomicInteger(N); }
   public boolean use() {
       while (true)
       {
          int n = this.count.get();
          if (n == 0)
             return false;
          if (this.count.compareAndSet(n, n-1))
             return true;
       }
   }

while.

CountDownLatch , countDown() w/r/t GetCount().

?

+3
3

AtomicBoolean:

final AtomicBoolean once = new AtomicBoolean(true);
Runnable r = new Runnable() {
    @Override public void run() {
        if (once.getAndSet(false))
           doSomething();
    }
}

, compareAndSet(). , getAndIncrement() .

+4

. AtomicInteger . getAndDecrement().

-

if(counter.getAndDecrement() > 0) {
   // something
} else {
   counter.set(0);
}

, . .. .

AtomicLong .

+1
// This implements an unfair locking scheme:
while ( mayContinue() ) {
    // acquire the permit and check if it was legally obtained
    if ( counter.decrementAndGet() > 0 )
        return true;
    // return the illegally acquired permit
    counter.incrementAndGet();
}
return false;

Setting the counter to zero, if you find that the permission was illegally obtained, creates a race condition when another thread releases the permission. This only works in situations where there are no more than 2 or 3 threads. Some other deferral or blocking mechanisms should be added if you have more.

0
source

All Articles