HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavaMinor

Fast non-fair semaphore

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
fastfairsemaphorenon

Problem

This is a simple non-fair semaphore implementation using Java atomic objects. It currently performs a little over twice as fast as java.util.concurrent.Semaphore on my simple test.

The busy-wait loop in acquire() calls the Runnable specified during construction, so that users can provide their own custom back-off strategy (such as looping for X iterations and then yielding, etc.)

I do not perform any checks on the parameters because I assume the users will not try to acquire 10 permits from a 1 permit instance.

Semaphore.java:

```
package cr.lockfree;

import java.util.concurrent.atomic.AtomicInteger;

/**
* Non-fair lock-free Semaphore with customizable back-off strategy for high
* contention scenarios.
*
* @author user2296177
* @version 1.0
*
*/
public class Semaphore {
/**
* Default back-off strategy to prevent busy-wait loop. Calls
* Thread.sleep(0, 1);. Has better performance and lower CPU usage than
* Thread.yield() inside busy-wait loop.
*/
private static Runnable defaultBackoffStrategy = () -> {
try {
Thread.sleep( 0, 1 );
} catch ( InterruptedException e ) {
e.printStackTrace();
}
};

private AtomicInteger permitCount;
private final Runnable backoffStrategy;

/**
* Construct a Semaphore instance with maxPermitCount permits and the
* default back-off strategy.
*
* @param maxPermitCount
* Maximum number of permits that can be distributed.
*/
public Semaphore( final int maxPermitCount ) {
this( maxPermitCount, defaultBackoffStrategy );
}

/**
* Construct a Semaphore instance with maxPermitCount permits and a custom
* Runnable to run a back-off strategy during contention.
*
* @param maxPermitCount
* Maximum number of permits that can be distributed.
* @param backoffStrategy
* Runnable back-off strategy to run during high contention.

Solution

Negative permit count check

In tryDecrementPermitCount(), I think this check:

if ( oldPermitCount == 0 || newPermitCount < 0 ) return false;


should just be:

if ( newPermitCount < 0 ) return false;


The original if statement confused me because both sides of the || are essentially checking the same thing.

Also, the comment for the function says that it will return false if the permitCount reaches zero, but that isn't true. It will only return false if the permitCount would become negative (after you fix the above problem).

Code Snippets

if ( oldPermitCount == 0 || newPermitCount < 0 ) return false;
if ( newPermitCount < 0 ) return false;

Context

StackExchange Code Review Q#109401, answer score: 4

Revisions (0)

No revisions yet.