# AQS 工具类分析

# 1. CountDownLatch

# API

  • state: 需要等待的线程数

method:

// 多种实现
public void await() throws InterruptedException {
    sync.acquireSharedInterruptibly(1);
}
public void countDown() {
    sync.releaseShared(1);
}
  • await:阻塞线程直到latch的数量为0
  • countDown:释放一个latch

使用的AQS的共享式队列。API支持中断,await的重载方法支持超时。

# 实现

一个静态final内部类实现Sync,维护AQS的state。

state表示还没有完成的任务数。

初始化为固定count,release时每次减1, 实现方法:

protected int tryAcquireShared(int acquires) {
    return (getState() == 0) ? 1 : -1;
}

protected boolean tryReleaseShared(int releases) {
    // Decrement count; signal when transition to zero
    for (;;) {
        int c = getState();
        if (c == 0)
            return false;
        int nextc = c-1;
        if (compareAndSetState(c, nextc))
            return nextc == 0;
    }
}

API只要使用await进行阻塞,countDown进行释放,state=0会唤醒全部阻塞的线程

# 2. Semaphore

Semaphore持有一定数量的permits,每次调用acquire()都将消耗一个许可,如果许不可用,则阻塞等待直到有许可被释放,每次调用release()都将归还一个许可。通常用来限制资源的访问次数。

Semaphore使用一个抽象的静态内部类Sync实现AQS,实现公共处理逻辑,然后使用NonfairSync和FairSync分别实现公平和非公平的同步器。

state表示许可的数量,每次acquire会减少,每次release会增加

通过实现AQS的tryAcquireShared和tryReleaseShared进行操作

NonfairSync的实现:

protected int tryAcquireShared(int acquires) {
    return nonfairTryAcquireShared(acquires);
}

// 父类Sync的实现:
final int nonfairTryAcquireShared(int acquires) {
    for (;;) {
        int available = getState();
        int remaining = available - acquires;
        if (remaining < 0 ||
            compareAndSetState(available, remaining))
            return remaining;
    }
}

可见获取锁就是从state减去个数

释放在Sync进行实现,公平和非公平模式都是同样的。


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;
    }
}

公平模式

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;
    }
}

多一个判断是否有排队。

Semaphore有个特点可以修改permit,即增加,减少,清空三种操作,其中增加利用Semaphore没有owner的特性,任何线程都可以调用release方法,减少和清空在Sync提供了方法

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;
    }
}

增加需要注意溢出的异常,减少注意为负值(溢出)的异常

# 应用示例

  1. ConcurrentHashMap的操作原子性实现并发修改
private static Map<String, Integer> counts = new ConcurrentHashMap<String, Integer>();
/**
 * 将指定的key值加1,借助数据结构的原子操作实现并发修改
 * @param specifiedKey
 */
public void increase(String specifiedKey) {
	while (true) {
		Integer count = counts.get(specifiedKey);
		if (null == count) {
			if (counts.putIfAbsent(specifiedKey, 1) == null) {
				break;
			}
		} else {
			if (counts.replace(specifiedKey, count, count + 1)) {
				break;
			}
		}
	}
}

# CyclicBarrier

用于等待多个线程都准备好,每一个线程准备好后 计数器加1 加到指定值后全部开始

# StampLock