今天看啥  ›  专栏  ›  我很丑

Java 并发编程(十五) -- Semaphore源码分析

我很丑  · 掘金  ·  · 2020-03-17 02:20
阅读 13

Java 并发编程(十五) -- Semaphore源码分析

1. 类的定义

public class Semaphore implements java.io.Serializable 
复制代码

2. 字段属性

//序列化版本号
private static final long serialVersionUID = -3222578661600680210L;
//同步器,AbstractQueuedSynchronizer的子类
private final Sync sync;
复制代码

从字段属性中可以看出

  • Semaphore的所有操作都是使用内部类Sync对象进行操作的

3. 构造方法

//传入信号数
public Semaphore(int permits) {
    	//默认使用非公平锁
        sync = new NonfairSync(permits);
    }
//传入信号数和锁的类型
public Semaphore(int permits, boolean fair) {
        sync = fair ? new FairSync(permits) : new NonfairSync(permits);
    }
复制代码

从构造方法中可以看出

  • 构造方法只做了一件事:初始化sync对象

4.方法

acquire 方法

//可中断的获取信号量
public void acquire() throws InterruptedException {
    	//调用sync的acquireSharedInterruptibly方法
        sync.acquireSharedInterruptibly(1);
    }

//获取指定数量的信号量
public void acquire(int permits) throws InterruptedException {
        if (permits < 0) throw new IllegalArgumentException();
    	//调用sync的acquireSharedInterruptibly方法
        sync.acquireSharedInterruptibly(permits);
    }
复制代码

acquireUninterruptibly 方法

//不可中断的获取信号量
public void acquireUninterruptibly() {
    	//调用sync的acquireShared方法
        sync.acquireShared(1);
    }
//不可中断的获取指定数量的信号量
public void acquireUninterruptibly(int permits) {
        if (permits < 0) throw new IllegalArgumentException();
        sync.acquireShared(permits);
    }
复制代码

tryAcquire 方法

//尝试获取信号量
public boolean tryAcquire() {
    	//调用sync的nonfairTryAcquireShared方法
        return sync.nonfairTryAcquireShared(1) >= 0;
    }

//尝试获取指定数量的信号量
public boolean tryAcquire(int permits) {
        if (permits < 0) throw new IllegalArgumentException();
    	//尝试获取指定数量的信号量
        return sync.nonfairTryAcquireShared(permits) >= 0;
    }

//设置超时时间的尝试获取信号量
public boolean tryAcquire(long timeout, TimeUnit unit)
        throws InterruptedException {
    	//调用sync的tryAcquireSharedNanos方法
        return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
    }

//设置超时时间的尝试获取指定数量的信号量
public boolean tryAcquire(int permits, long timeout, TimeUnit unit)
        throws InterruptedException {
        if (permits < 0) throw new IllegalArgumentException();
    	//调用sync的tryAcquireSharedNanos方法
        return sync.tryAcquireSharedNanos(permits, unit.toNanos(timeout));
    }
复制代码

release 方法

//释放一个信号量
public void release() {
    	//调用sync的releaseShared方法
        sync.releaseShared(1);
    }
//释放指定数量的信号量
public void release(int permits) {
        if (permits < 0) throw new IllegalArgumentException();
        sync.releaseShared(permits);
    }
复制代码

availablePermits 方法

//获取当前可用的通道数
public int availablePermits() {
        return sync.getPermits();
    }
复制代码

drainPermits 方法

//获取立即可用的通道数
public int drainPermits() {
        return sync.drainPermits();
    }
复制代码

reducePermits 方法

//减少信号数
protected void reducePermits(int reduction) {
        if (reduction < 0) throw new IllegalArgumentException();
        sync.reducePermits(reduction);
    }
复制代码

isFair 方法

//获取锁的类型, true 公平锁, false 非公平锁
public boolean isFair() {
        return sync instanceof FairSync;
    }
复制代码

hasQueuedThreads 方法

//队列中是否有正在等信号的线程
public final boolean hasQueuedThreads() {
        return sync.hasQueuedThreads();
    }
复制代码

getQueueLength 方法

//获取队列中等待信号的线程数
public final int getQueueLength() {
        return sync.getQueueLength();
    }
复制代码

getQueuedThreads 方法

//获取队列中的线程,以集合的方式返回
protected Collection<Thread> getQueuedThreads() {
        return sync.getQueuedThreads();
    }
复制代码

5. 内部类Sync

1. 类的定义

abstract static class Sync extends AbstractQueuedSynchronizer
复制代码

从类的定义中可以看出

  • Sync是一个抽象的静态内部类,使用模板方法的设计模式让子类继承
  • Sync继承AbstractQueuedSynchronizer类

2. 字段属性

//序列化版本号
private static final long serialVersionUID = 1192457210091910933L;
复制代码

3. 构造方法

//传入的信号数就是AQS中的state
Sync(int permits) {
            setState(permits);
        }

复制代码

4. 方法

getPermits 方法
//获取信号数
final int getPermits() {
    		//实质上就是获取state的值
            return getState();
        }

复制代码
nonfairTryAcquireShared 方法
//非公平方式获取共享锁,返回剩余可用信号数
final int nonfairTryAcquireShared(int acquires) {
    		//for无限循环,自旋CAS
            for (;;) {
                //获取当前的state
                int available = getState();
                //可用信号-获取数量=剩余可用数量
                int remaining = available - acquires;
                if (remaining < 0 ||
                    compareAndSetState(available, remaining))
                    return remaining;
            }
        }

复制代码
tryReleaseShared 方法
//尝试释放共享锁
protected final boolean tryReleaseShared(int releases) {
    		//for无限循环,自旋CAS
            for (;;) {
                //获取当前的state
                int current = getState();
                //可用信号+释放数量=新的可用数量
                int next = current + releases;
                if (next < current) // overflow
                    //releases小于0 抛出异常
                    throw new Error("Maximum permit count exceeded");
                //CAS,设置新值
                if (compareAndSetState(current, next))
                    return true;
            }
        }

复制代码
reducePermits 方法
//减少信号数量
final void reducePermits(int reductions) {
    		//for无限循环,自旋CAS
            for (;;) {
                //获取当前的state
                int current = getState();
                //可用信号-减少的数量=新的可用数量
                int next = current - reductions;
                if (next > current) // underflow
                    //reductions小于0 抛出异常
                    throw new Error("Permit count underflow");
                //CAS,设置新值
                if (compareAndSetState(current, next))
                    return;
            }
        }

复制代码
drainPermits 方法
//清空信号
final int drainPermits() {
    		//CAS 自旋把state置为0
            for (;;) {
                int current = getState();
                if (current == 0 || compareAndSetState(current, 0))
                    return current;
            }
        }

复制代码

6. 内部类 NonfairSync

1. 类的定义

static final class NonfairSync extends Sync

复制代码

从类的定义可以看出

  • NonfairSync是Sync的子类

2. 字段属性

//序列化版本号
private static final long serialVersionUID = -2694183684443567898L;

复制代码

3. 构造方法

//设置state
NonfairSync(int permits) {
            super(permits);
        }

复制代码

4. 方法

tryAcquireShared 方法
//尝试获取共享锁
protected int tryAcquireShared(int acquires) {
    		//调用父类的方法nonfairTryAcquireShared,直接抢锁
            return nonfairTryAcquireShared(acquires);
        }

复制代码

7. 内部类FairSync

1. 类的定义

 static final class FairSync extends Sync

复制代码

从类的定义中可以看出

  • FairSync继承Sync类

2. 字段属性

//序列化版本号
private static final long serialVersionUID = 2014338818796000944L;

复制代码

3. 构造方法

//设置state
FairSync(int permits) {
            super(permits);
        }

复制代码

方法

tryAcquireShared 方法
//尝试获取共享锁
protected int tryAcquireShared(int acquires) {
            for (;;) {
                //先看队列中是否有线程排队
                if (hasQueuedPredecessors())
                    return -1;
                //获取state的值
                int available = getState();
                //可用信号-获取数量=剩余可用数量
                int remaining = available - acquires;
                if (remaining < 0 ||
                    compareAndSetState(available, remaining))
                    return remaining;
            }
        }

复制代码




原文地址:访问原文地址
快照地址: 访问文章快照