Java并发编程Semaphore

信号量

信号量类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 <thread.length; i++) {
			thread[i]=new Thread(new Job(p),"Thread"+i);
		}
		for (int i = 0; i < thread.length; i++) {
			thread[i].start();
		}
	}
}
----------------------输出结果 ---------------------------
执行打印Thread0花费时间9秒
文档被打印Thread0
执行打印Thread3花费时间9秒
文档被打印Thread3
执行打印Thread2花费时间6秒
文档被打印Thread2
执行打印Thread1花费时间4秒
文档被打印Thread1
执行打印Thread5花费时间6秒
文档被打印Thread5
执行打印Thread7花费时间3秒
文档被打印Thread7
执行打印Thread9花费时间8秒
文档被打印Thread9
执行打印Thread8花费时间0秒
文档被打印Thread8
执行打印Thread6花费时间8秒
文档被打印Thread6
执行打印Thread4花费时间7秒
文档被打印Thread4

如上声明一个打印队列,构造器初始化信号量对象来保护对打印队列的访问。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

原文地址:https://www.cnblogs.com/tonyY/p/5088832.html