程序猿学社的GitHub,欢迎Star
https://github.com/ITfqyd/cxyxs
本文已记录到github,形成对应专题。
随着18年开始,各个公司的面试难度,也不断在提升,面试也不仅仅停留再ArrayList底层是如何实现的。本文就来介绍一下,我们面试经常会问的一个Semaphore,CountDownLatch、CyclicBarrier都有什么区别。本来 就来说道说道Semaphore。
Semaphore是jdk 1.5以引入的,同版本引入的还有他的两个同胞兄弟,CountDownLatch和CyclicBarrier。位于java.util.concurrent报下,一般简称juc。
一个计数信号量。 在概念上,信号量维持一组许可证,如果有必要,每个acquire()都会阻塞,直到许可证可用,然后才能使用它。 每个release()添加许可证。
方法 | 描述 |
---|---|
Semaphore(int permits) | 创建一个 Semaphore与给定数量的许可证和非公平公平设置 |
Semaphore(int permits, boolean fair) | 创建一个 Semaphore与给定数量的许可证和给定的公平设置。 |
acquire() | 从该信号量获取许可证,阻止直到可用 |
acquire(int permits) | 从该信号量获取给定数量的许可证,阻止直到所有可用 |
release() | 释放许可证 |
release(int permits) | 释放一定数量的许可证 |
模拟一个餐厅叫号,吃饭,结算的一个场景,有4张单人桌子,来了10个客人过来吃饭的一个场景。通过信号量来实现。
package com.cxyxs.thread.fourteen;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
/**
* Description:
* Author: 程序猿学社
* Date: 2020/3/6 18:41
* Modified By:
*/
public class Demo1 {
public static void main(String[] args) {
//4表示4张桌子
Semaphore semaphore = new Semaphore(4);
for (int i=0;i<10;i++) {
final int index=i;
new Thread(()->{
try {
//1.被服务员叫号 分发许可证
semaphore.acquire();
//2.开始吃饭
System.out.println(Thread.currentThread().getName()+"被服务员叫号后,准备上桌吃饭");
//3.吃饭中 模拟吃饭2s
TimeUnit.SECONDS.sleep(2);
//4.吃完饭,喊服务员结算
semaphore.release();
System.out.println(Thread.currentThread().getName()+"喊服务员结算!");
} catch (InterruptedException e) {
e.printStackTrace();
}
},"客人"+index).start();
}
}
}
运行结果
客人0被服务员叫号后,准备上桌吃饭
客人2被服务员叫号后,准备上桌吃饭
客人1被服务员叫号后,准备上桌吃饭
客人3被服务员叫号后,准备上桌吃饭
客人1喊服务员结算!
客人6被服务员叫号后,准备上桌吃饭
客人3喊服务员结算!
客人5被服务员叫号后,准备上桌吃饭
客人4被服务员叫号后,准备上桌吃饭
客人7被服务员叫号后,准备上桌吃饭
客人2喊服务员结算!
客人0喊服务员结算!
客人4喊服务员结算!
客人5喊服务员结算!
客人9被服务员叫号后,准备上桌吃饭
客人8被服务员叫号后,准备上桌吃饭
客人6喊服务员结算!
客人7喊服务员结算!
客人9喊服务员结算!
客人8喊服务员结算!
Semaphore semaphore = new Semaphore(4,true);
public Semaphore(int permits, boolean fair) {
sync = fair ? new FairSync(permits) : new NonfairSync(permits);
}
private volatile int state;
/**
* Sets the value of synchronization state.
* This operation has memory semantics of a {@code volatile} write.
* @param newState the new state value
*/
protected final void setState(int newState) {
state = newState;
}
public void acquire(int permits) throws InterruptedException {
if (permits < 0) throw new IllegalArgumentException();
sync.acquireSharedInterruptibly(permits);
}
public final void acquireSharedInterruptibly(int arg)
throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
if (tryAcquireShared(arg) < 0)
doAcquireSharedInterruptibly(arg);
}
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;
}
}
简单的理解CAS是怎么一回事。并且,他经常露脸压线,不抓你,抓谁。通过一个简单的小例子,理解一下CAS
public static void main(String[] args) {
AtomicInteger atomicInteger = new AtomicInteger(1);
atomicInteger.compareAndSet(1,2);
System.out.println(atomicInteger.get());
}
public final boolean compareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
public void release(int permits) {
if (permits < 0) throw new IllegalArgumentException();
sync.releaseShared(permits);
}
public final boolean releaseShared(int arg) {
if (tryReleaseShared(arg)) {
doReleaseShared();
return true;
}
return false;
}
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;
}
}
源码学习实际上没有我们想象中的类,最近我们看了几个类,发现底层的调用都类似。
觉得不错,可以通过github关注我的工号,文章已整理成对应的专题,会不定期的推送。
github