首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >快速不公平信号量

快速不公平信号量
EN

Code Review用户
提问于 2015-10-31 20:43:41
回答 1查看 715关注 0票数 7

这是一个使用Java原子对象的简单的非公平信号量实现。在我的简单测试中,它目前的执行速度是java.util.concurrent.Semaphore的两倍多。

acquire()中的繁忙等待循环调用构造期间指定的Runnable,这样用户就可以提供自己的自定义回退策略(例如循环X迭代,然后再生成,等等)。

我不对参数执行任何检查,因为我假设用户不会尝试从一个许可证实例中获取10个许可证。

Semaphore.java:

代码语言:javascript
复制
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;
    }
}
EN

回答 1

Code Review用户

回答已采纳

发布于 2015-11-01 00:37:32

阴性许可证计数检查

tryDecrementPermitCount()中,我认为这张支票:

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

应该是:

代码语言:javascript
复制
        if ( newPermitCount < 0 ) return false;

最初的if语句使我感到困惑,因为||的双方本质上都在检查相同的内容。

此外,函数的注释说,如果permitCount达到零,它将返回false,但这不是真的。只有当permitCount变成负值时(在您修复了上面的问题之后),它才会返回false。

票数 4
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/109401

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档