这是一个使用Java原子对象的简单的非公平信号量实现。在我的简单测试中,它目前的执行速度是java.util.concurrent.Semaphore的两倍多。
acquire()中的繁忙等待循环调用构造期间指定的Runnable,这样用户就可以提供自己的自定义回退策略(例如循环X迭代,然后再生成,等等)。
我不对参数执行任何检查,因为我假设用户不会尝试从一个许可证实例中获取10个许可证。
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.
*/
public Semaphore( final int maxPermitCount, final Runnable backoffStrategy ) {
permitCount = new AtomicInteger( maxPermitCount );
this.backoffStrategy = backoffStrategy;
}
/**
* Attempt to acquire one permit and immediately return.
*
* @return true : acquired one permits.<br>
* false: did not acquire one permit.
*/
public boolean tryAcquire() {
return tryAcquire( 1 );
}
/**
* Attempt to acquire n permits and immediately return.
*
* @param n
* Number of permits to acquire.
* @return true : acquired n permits.<br>
* false: did not acquire n permits.
*/
public boolean tryAcquire( final int n ) {
return tryDecrementPermitCount( n );
}
/**
* Acquire one permit.
*/
public void acquire() {
acquire( 1 );
}
/**
* Acquire n permits.
*
* @param n
* Number of permits to acquire.
*/
public void acquire( final int n ) {
while ( !tryDecrementPermitCount( n ) ) {
backoffStrategy.run();
}
}
/**
* Release one permit.
*/
public void release() {
release( 1 );
}
/**
* Release n permits.
*
* @param n
* Number of permits to release.
*/
public void release( final int n ) {
permitCount.addAndGet( n );
}
/**
* Try decrementing the current number of permits by n.
*
* @param n
* The number to decrement the number of permits.
* @return true : the number of permits was decremented by n.<br>
* false: decrementing the number of permits results in a negative
* value or zero.
*/
private boolean tryDecrementPermitCount( final int n ) {
int oldPermitCount;
int newPermitCount;
do {
oldPermitCount = permitCount.get();
newPermitCount = oldPermitCount - n;
if ( newPermitCount > n ) throw new ArithmeticException( "Overflow" );
if ( oldPermitCount == 0 || newPermitCount < 0 ) return false;
} while ( !permitCount.compareAndSet( oldPermitCount, newPermitCount ) );
return true;
}
}发布于 2015-11-01 00:37:32
在tryDecrementPermitCount()中,我认为这张支票:
if ( oldPermitCount == 0 || newPermitCount < 0 ) return false;
应该是:
if ( newPermitCount < 0 ) return false;最初的if语句使我感到困惑,因为||的双方本质上都在检查相同的内容。
此外,函数的注释说,如果permitCount达到零,它将返回false,但这不是真的。只有当permitCount变成负值时(在您修复了上面的问题之后),它才会返回false。
https://codereview.stackexchange.com/questions/109401
复制相似问题