Semaphore 深入源码解析

  Semaphore(信号量),内部维护了一组许可证,通过acquire、tryAcquire方法获取许可证,acquire获取不到许可时,会阻塞线程。tryAcquire获取不到许可时,会返回获取结果。通过release释放许可,释放许可会添加可用许可证数量。Semaphore借助AQS实现的共享锁,通过构造参数可以给状态变量赋值,用来控制对资源访问的并发度。

  演示示例:

package com.securitit.serialize.juc;

import java.util.Date;
import java.util.concurrent.Semaphore;

import org.assertj.core.util.DateUtil;

public class SemaphoreTester {

	// Semaphore实例.
	private static final Semaphore semaphore = new Semaphore(2);

	public static void main(String[] args) {
		// 模拟线程.
		new Thread(() -> {
			try {
				System.out.println(
						DateUtil.formatAsDatetime(new Date()) + " " + Thread.currentThread().getName() + " 获取许可开始.");
				semaphore.acquire();
				System.out.println(
						DateUtil.formatAsDatetime(new Date()) + " " + Thread.currentThread().getName() + " 获取许可成功.");
				Thread.sleep(5000);
			} catch (InterruptedException ex) {
				ex.printStackTrace();
			} finally {
				semaphore.release();
				System.out.println(
						DateUtil.formatAsDatetime(new Date()) + " " + Thread.currentThread().getName() + " 释放许可成功.");
			}
		}).start();
		// 模拟线程.
		new Thread(() -> {
			try {
				System.out.println(
						DateUtil.formatAsDatetime(new Date()) + " " + Thread.currentThread().getName() + " 获取许可开始.");
				semaphore.acquire();
				System.out.println(
						DateUtil.formatAsDatetime(new Date()) + " " + Thread.currentThread().getName() + " 获取许可成功.");
				Thread.sleep(5000);
			} catch (InterruptedException ex) {
				ex.printStackTrace();
			} finally {
				semaphore.release();
				System.out.println(
						DateUtil.formatAsDatetime(new Date()) + " " + Thread.currentThread().getName() + " 释放许可成功.");
			}
		}).start();
		// 模拟线程.
		new Thread(() -> {
			try {
				System.out.println(
						DateUtil.formatAsDatetime(new Date()) + " " + Thread.currentThread().getName() + " 获取许可开始.");
				semaphore.acquire();
				System.out.println(
						DateUtil.formatAsDatetime(new Date()) + " " + Thread.currentThread().getName() + " 获取许可成功.");
				Thread.sleep(2000);
			} catch (InterruptedException ex) {
				ex.printStackTrace();
			} finally {
				semaphore.release();
				System.out.println(
						DateUtil.formatAsDatetime(new Date()) + " " + Thread.currentThread().getName() + " 释放许可成功.");
			}
		}).start();
	}

}

  输出结果:

2020-06-26T23:19:28 Thread-0 获取许可开始.
2020-06-26T23:19:28 Thread-1 获取许可开始.
2020-06-26T23:19:28 Thread-2 获取许可开始.
2020-06-26T23:19:28 Thread-0 获取许可成功.
2020-06-26T23:19:28 Thread-1 获取许可成功.
2020-06-26T23:19:33 Thread-1 释放许可成功.
2020-06-26T23:19:33 Thread-2 获取许可成功.
2020-06-26T23:19:33 Thread-0 释放许可成功.
2020-06-26T23:19:35 Thread-2 释放许可成功.

  线程Thread-0和Thread-1首先获取许可成功,由于许可数量只有两个,线程Thread-2进入阻塞状态,等待Thread-0和Thread-1释放许可。然后,Thread-1释放许可,Thread-2获取许可成功,继而Thread-0和Thread-2释放许可。

  源码分析:

package java.util.concurrent;
import java.util.Collection;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;

public class Semaphore implements java.io.Serializable {
    // 序列化版本号.
    private static final long serialVersionUID = -3222578661600680210L;
    // 同步类实例.
    private final Sync sync;
	// 同步类.内部类.扩展AQS实现.
    abstract static class Sync extends AbstractQueuedSynchronizer {
        // 序列化版本号.
        private static final long serialVersionUID = 1192457210091910933L;
		// Constructor.
        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 ||
                    // 以CAS方式设置剩余许可数.
                    compareAndSetState(available, remaining))
                    return remaining;
            }
        }
		// 尝试释放共享锁.
        protected final boolean tryReleaseShared(int releases) {
            for (;;) {
                int current = getState();
                int next = current + releases;
                if (next < current) // overflow
                    throw new Error("Maximum permit count exceeded");
                if (compareAndSetState(current, next))
                    return true;
            }
        }
		// 减少许可数量.
        final void reducePermits(int reductions) {
            for (;;) {
                int current = getState();
                int next = current - reductions;
                if (next > current) // underflow
                    throw new Error("Permit count underflow");
                if (compareAndSetState(current, next))
                    return;
            }
        }
		// 设置许可数量.
        final int drainPermits() {
            for (;;) {
                int current = getState();
                if (current == 0 || compareAndSetState(current, 0))
                    return current;
            }
        }
    }
	// 非公平内部类实现.继承自Sync.
    static final class NonfairSync extends Sync {
        // 序列化版本号.
        private static final long serialVersionUID = -2694183684443567898L;
		// 非公平Constructor.
        NonfairSync(int permits) {
            super(permits);
        }
		// 尝试获取共享锁.
        protected int tryAcquireShared(int acquires) {
            return nonfairTryAcquireShared(acquires);
        }
    }
	// 公平内部类实现,继承自Sync.
    static final class FairSync extends Sync {
        // 序列化版本号.
        private static final long serialVersionUID = 2014338818796000944L;
		// 公平Constructor.
        FairSync(int permits) {
            super(permits);
        }
		// 尝试释放共享锁.
        protected int tryAcquireShared(int acquires) {
            for (;;) {
                if (hasQueuedPredecessors())
                    return -1;
                int available = getState();
                int remaining = available - acquires;
                if (remaining < 0 ||
                    compareAndSetState(available, remaining))
                    return remaining;
            }
        }
    }
	// Constructor.
    public Semaphore(int permits) {
        sync = new NonfairSync(permits);
    }
	// Constructor.提供额外的公平性参数.
    public Semaphore(int permits, boolean fair) {
        sync = fair ? new FairSync(permits) : new NonfairSync(permits);
    }
	// 以阻塞的方式获取许可.
    public void acquire() throws InterruptedException {
        sync.acquireSharedInterruptibly(1);
    }
	// 以可中断的方式获取许可.
    public void acquireUninterruptibly() {
        sync.acquireShared(1);
    }
	// 尝试获取许可,快速成功失败.
    public boolean tryAcquire() {
        return sync.nonfairTryAcquireShared(1) >= 0;
    }
	// 尝试获取许可,快速成功失败.可指定超时时间.
    public boolean tryAcquire(long timeout, TimeUnit unit)
        throws InterruptedException {
        return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
    }
	// 释放资源.
    public void release() {
        sync.releaseShared(1);
    }
	// 指定释放资源数.
    public void acquire(int permits) throws InterruptedException {
        if (permits < 0) throw new IllegalArgumentException();
        sync.acquireSharedInterruptibly(permits);
    }
	// 尝试获取许可,快速成功失败.可响应中断.
    public void acquireUninterruptibly(int permits) {
        if (permits < 0) throw new IllegalArgumentException();
        sync.acquireShared(permits);
    }
	//  尝试获取许可,快速成功失败.
    public boolean tryAcquire(int permits) {
        if (permits < 0) throw new IllegalArgumentException();
        return sync.nonfairTryAcquireShared(permits) >= 0;
    }
	//  尝试获取许可,快速成功失败.可指定超时时间.
    public boolean tryAcquire(int permits, long timeout, TimeUnit unit)
        throws InterruptedException {
        if (permits < 0) throw new IllegalArgumentException();
        return sync.tryAcquireSharedNanos(permits, unit.toNanos(timeout));
    }
	// 释放指定数量的许可.
    public void release(int permits) {
        if (permits < 0) throw new IllegalArgumentException();
        sync.releaseShared(permits);
    }
	// 可用许可数量.
    public int availablePermits() {
        return sync.getPermits();
    }
	// 已用许可数量.
    public int drainPermits() {
        return sync.drainPermits();
    }
	// 减少许可数量.
    protected void reducePermits(int reduction) {
        if (reduction < 0) throw new IllegalArgumentException();
        sync.reducePermits(reduction);
    }
	// 是否公平.
    public boolean isFair() {
        return sync instanceof FairSync;
    }
	// 同步队列中是否有线程.
    public final boolean hasQueuedThreads() {
        return sync.hasQueuedThreads();
    }
	// 获取同步队列长度.
    public final int getQueueLength() {
        return sync.getQueueLength();
    }
	// 获取队列线程集合.
    protected Collection<Thread> getQueuedThreads() {
        return sync.getQueuedThreads();
    }
	// 重写toString方法.
    public String toString() {
        return super.toString() + "[Permits = " + sync.getPermits() + "]";
    }
}

  Semaphore源码结构很简单,Sync这个内部类是最主要的。Semaphore完全依赖于AQS的共享锁禁止来实现许可的发放和回收。

  注:文中源码均来自于JDK1.8版本,不同版本间可能存在差异。

  如果有哪里有不明白或不清楚的内容,欢迎留言哦!

猜你喜欢

转载自blog.csdn.net/securitit/article/details/106984619