patternjavaMinor
Fast non-fair semaphore
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
The busy-wait loop in
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.
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
should just be:
The original
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).
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.