2

次の機能を備えたセマフォが必要です。

  1. ノンブロッキングである必要があります。つまり、スレッドが許可を取得できない場合は、待機せずに先に進む必要があります
  2. 再入不可にする必要があります。つまり、同じスレッドが保護されたコードに 2 回入る場合、1 つではなく 2 つの許可を取得する必要があります。

私は次のコードを書きました:

public class SimpleSemaphore
{

    private int permits;

    private AtomicLong counter = new AtomicLong();

    SimpleSemaphore(int permits)
    {
        this.permits = permits;
    }

    boolean acquire()
    {

        if (counter.incrementAndGet() < permits)
        {
            return true;
        }
        else
        {
            counter.decrementAndGet();
            return false;
        }

    }

    void release()
    {
        counter.decrementAndGet();

    }
}

別のオプションは、このセマフォです。

public class EasySemaphore
{

    private int permits;

    private AtomicLong counter = new AtomicLong();

    EasySemaphore(int permits)
    {
        this.permits = permits;
    }

    boolean acquire()
    {
        long index = counter.get();

        if (index < permits)
        {
            if (counter.compareAndSet(index, index + 1))
            {
                return true;
            }
        }

        return false;
    }

    void release()
    {
        counter.decrementAndGet();
    }
}

どちらの実装もスレッドセーフで正しい​​ですか? どちらの方がよいですか?このタスクをどのように進めますか?

4

2 に答える 2

7

すでにそれをすべて行っていませんjava.util.concurrent.Semaphoreか?

tryAcquireノンブロッキングの取得があり、残りの許可の単純なカウントを維持します (同じスレッドが複数取得する可能性があります) 。

于 2012-09-26T08:22:03.473 に答える
0

カウンターが0よりも大きくなることは決してないので、2番目の方が優れていると思います(そして、わずかに効率的です)

そうしないと、許可がまだ残っているときにメソッドが失敗する可能性があります。

public class EasySemaphore {
    private final AtomicInteger counter;

    EasySemaphore(int permits) {
        counter = new AtomicInteger(permits);
    }

    boolean acquire() {
        // highly unlikely to loop more than once.
        while(true) {
            int count = counter.get();
            if (count <= 0) return false;
            if (counter.compareAndSet(count, count -1)) 
                return true;
        }
    }

    void release() {
        counter.incrementAndGet();
    }
}
于 2012-09-26T08:23:18.293 に答える