java并发编程之美 学习笔记
Semaphore
demo
实现CountDownLatch功能
public class SemaphoreTest1 {
private static Semaphore semaphore = new Semaphore(0);
public static void main(String[] args) throws InterruptedException {
System.out.println("main线程执行start....");
ExecutorService executorService = Executors.newFixedThreadPool(2);
executorService.submit(() -> {
System.out.println("我是线程1");
semaphore.release(1); //释放1个信号量
});
executorService.submit(() -> {
System.out.println("我是线程2");
semaphore.release(); //释放1个信号量
});
//请求两个信号量
semaphore.acquire(2);
System.out.println("main线程执行end----");
executorService.shutdown();
}
}
运行结果:
实现CyclicBarrier
public class SemaphoreTest2 {
private static Semaphore semaphore = new Semaphore(0);
public static void main(String[] args) throws InterruptedException {
ExecutorService executorService = new ThreadPoolExecutor(2, 2, 0l, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
executorService.submit(() -> {
System.out.println("A arrived ----- Step1");
semaphore.release();
});
executorService.submit(() -> {
try {
System.out.println("B arrived ----- Step1");
//B to buy something ...
Thread.sleep(30);
semaphore.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
semaphore.acquire(2);
System.out.println("Step1 finished ......");
executorService.submit(() -> {
System.out.println("A arrived ----- Step2");
semaphore.release();
});
executorService.submit(() -> {
try {
System.out.println("B arrived ----- Step2");
//B to buy something ...
Thread.sleep(50);
semaphore.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
semaphore.acquire(2);
System.out.println("Step2 finished ......");
executorService.shutdown();
}
}
运行结果:
源码分析
结构
public class Semaphore implements java.io.Serializable {
private final Sync sync;
//继承AQS锁
abstract static class Sync extends AbstractQueuedSynchronizer {...}
//非公平策略
static final class NonfairSync extends Sync {...}
//公平策略
static final class FairSync extends Sync {...}
}
构造函数
public Semaphore(int permits) {
//默认使用非公平策略
sync = new NonfairSync(permits);
}
public Semaphore(int permits, boolean fair) {
sync = fair ? new FairSync(permits) : new NonfairSync(permits);
}
acquire()
申请信号量,
//1.
//1.1 不带有参数,默认申请1个信号量
public void acquire() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
//1.2 带有permits参数个信号量
public void acquire(int permits) throws InterruptedException {
if (permits < 0) throw new IllegalArgumentException();
//2.
sync.acquireSharedInterruptibly(permits);
}
//2.AQS#acquireSharedInterruptibly
public final void acquireSharedInterruptibly(int arg)
throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
//3.
if (tryAcquireShared(arg) < 0)
//4. 当尝试获取锁失败,加入阻塞队列
doAcquireSharedInterruptibly(arg);
}
/3.1非公平策略
//3.1 NonfairSync.tryAcquireShared
protected int tryAcquireShared(int acquires) {
//3.1.1
return nonfairTryAcquireShared(acquires);
}
//3.1.1 Sync.nonfairTryAcquireShared
final int nonfairTryAcquireShared(int acquires) {
for (;;) {
//获取当前信号量值
int available = getState();
//计算剩余信号量 = 当前信号量 - 申请信号量
int remaining = available - acquires;
//如果剩余信号量 < 0, 直接返回 ---- 后续会将当前线程加入阻塞队列
//如果剩余信号量 > 0, CAS操作更新信号量数, ----- 后续会直接返回;
if (remaining < 0 ||
compareAndSetState(available, remaining))
return remaining;
}
}
/3.2公平策略
//3.2 FairSync.tryAcquireShared
protected int tryAcquireShared(int acquires) {
for (;;) {
//看当前线程节点的前驱节点是否也在等待获取该资源
//如果是,则自己放弃获取的权限,然后当前线程会被放入 AQS 阻塞队列
if (hasQueuedPredecessors())
return -1;
int available = getState();
int remaining = available - acquires;
if (remaining < 0 ||
compareAndSetState(available, remaining))
return remaining;
}
}
release
释放信号量。
//1. Semaphore.release
//1.1 不带有参数,释放信号量--默认释放1
public void release() {
sync.releaseShared(1);
}
//1.2 释放permits个信号量
public void release(int permits) {
if (permits < 0) throw new IllegalArgumentException();
sync.releaseShared(permits);
}
//2.AQS.releaseShared
public final boolean releaseShared(int arg) {
//3.
if (tryReleaseShared(arg)) {
//4.当tryReleaseShared返回true时,激活阻塞队列中的线程
doReleaseShared();
return true;
}
return false;
}
//3.Sync.tryReleaseShared
protected final boolean tryReleaseShared(int releases) {
for (;;) {
int current = getState();
//信号量增加releases
int next = current + releases;
if (next < current) // overflow
throw new Error("Maximum permit count exceeded");
//CAS 更新信号量
if (compareAndSetState(current, next))
return true;
}
}
这里请注意: 如果
current + releases
即release操作之后的信号量总数大于初始的信号量数,原始的信号量则或增大
至current + releases