Java同時プログラミングSemaphore

4002 ワード

しんごうりょう


信号量クラスSemaphoreは、一意の共有リソースへのアクセスを保護するために使用されます.単純な印刷キューで、同時にタスクを印刷し、信号量を加えて同時にスレッドを印刷することができます.
import java.util.concurrent.Semaphore;

public class PrintQueue {
    public PrintQueue() {

        semaphore = new Semaphore(1,true);
    }

    private final Semaphore semaphore;

    public void printJob(Object document) {
        try {
            semaphore.acquire();

            long duration = (long) (Math.random() * 10);

            System.out.println(" "+Thread.currentThread().getName() + " "+ duration+ " ");
            Thread.sleep(duration);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally{
            semaphore.release();
        }
    }
}


public class Job  implements Runnable{

    private PrintQueue printQueue;
    
    public Job(PrintQueue printQueue){
        
        this.printQueue=printQueue;
    }
    @Override
    public void run() {
        printQueue.printJob(new Object());
        System.out.println(" "+Thread.currentThread().getName());
    }
}

public class Main {
    public static void main(String[] args) {
        PrintQueue p = new PrintQueue();
        Thread thread[] = new Thread[10];
        for (int i = 0; i 

上記のように印刷キューを宣言すると、コンストラクタは信号量オブジェクトを初期化して印刷キューへのアクセスを保護します.semaphore.acquire();信号量を取得し、最後にsemaphore.release();リリースに使用します.10個のスレッドを開始して印刷を行い、最初に信号量を得たスレッドは臨界領域にアクセスでき、残りのスレッドは信号量が解放されるまで信号量によってブロックされる.信号量が解放されると、待機中のスレッドが選択され、臨界領域にアクセスできます.

単純コード解析


     boolean fair , 
    /**
     * Creates a {@code Semaphore} with the given number of
     * permits and the given fairness setting.
     *
     * @param permits the initial number of permits available.
     *        This value may be negative, in which case releases
     *        must occur before any acquires will be granted.
     * @param fair {@code true} if this semaphore will guarantee
     *        first-in first-out granting of permits under contention,
     *        else {@code false}
     */
    public Semaphore(int permits, boolean fair) {
        sync = (fair)? new FairSync(permits) : new NonfairSync(permits);
    }

    FairSync   NonfairSync  Sync  , Sync   AbstractQueuedSynchronizer
   /**
     * Synchronization implementation for semaphore.  Uses AQS state
     * to represent permits. Subclassed into fair and nonfair
     * versions.
     */
    abstract static class Sync extends AbstractQueuedSynchronizer {
        private static final long serialVersionUID = 1192457210091910933L;

        Sync(int permits) {
            setState(permits);
        }

        final int getPermits() {
            return getState();
        }

        final int nonfairTryAcquireShared(int acquires) {
            for (;;) {
                int available = getState();
                int remaining = available - acquires;
                if (remaining < 0 ||
                    compareAndSetState(available, remaining))
                    return remaining;
            }
        }

        protected final boolean tryReleaseShared(int releases) {
            for (;;) {
                int p = getState();
                if (compareAndSetState(p, p + releases))
                    return true;
            }
        }

        final void reducePermits(int reductions) {
            for (;;) {
                int current = getState();
                int next = current - reductions;
                if (compareAndSetState(current, next))
                    return;
            }
        }

        final int drainPermits() {
            for (;;) {
                int current = getState();
                if (current == 0 || compareAndSetState(current, 0))
                    return current;
            }
        }
    }


参考文献


Java同時プログラミングAbstractQueuedSynchronizer