最后总结
ActiveMQ+Kafka+RabbitMQ学习笔记PDF
关于分布式,限流+缓存+缓存,这三大技术(包含:ZooKeeper+Nginx+MongoDB+memcached+Redis+ActiveMQ+Kafka+RabbitMQ)等等。这些相关的面试也好,还有手写以及学习的笔记PDF,都是啃透分布式技术必不可少的宝藏。以上的每一个专题每一个小分类都有相关的介绍,并且小编也已经将其整理成PDF啦
semaphore.release();//释放一个资源许可
10个资源许可被取完后,再来线程获取就会入队列阻塞。
Semaphore
是在AQS
基础上实现的共享锁,获取资源和释放资源都是调用的AQS中共享锁模板方法,故只需要看tryAcquireShared
和tryReleaseShared
在Semaphore
中的实现。
首先初始化Semaphore,给资源许可5个,模拟多个线程获取资源。
public class Test1072 {
private static Semaphore semaphore = new Semaphore(5);
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
Thread thread = new Thread(new MyThread(i));
thread.start();
}
}
static class MyThread implements Runnable{
private int i;
public MyThread(int i) {
this.i = i;
}
@Override
public void run() {
try {
semaphore.acquire();
System.out.println(Thread.currentThread().getName() + “, semaphore.acquire()获取资源–” + i);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
// System.out.println(Thread.currentThread().getName() + “,semaphore.release()释放资源–” + i);
// semaphore.release();
}
}
}
}
//控制台输出
//线程只获取资源不释放
Thread-0, semaphore.acquire()获取资源–0
Thread-1, semaphore.acquire()获取资源–1
Thread-2, semaphore.acquire()获取资源–2
Thread-6, semaphore.acquire()获取资源–6
Thread-3, semaphore.acquire()获取资源–3
//线程获取资源并释放资源
Thread-0, semaphore.acquire()获取资源–0
Thread-2, semaphore.acquire()获取资源–2
Thread-2,semaphore.release()释放资源–2
Thread-1, semaphore.acquire()获取资源–1
Thread-1,semaphore.release()释放资源–1
Thread-0,semaphore.release()释放资源–0
Thread-3, semaphore.acquire()获取资源–3
Thread-3,semaphore.release()释放资源–3
Thread-5, semaphore.acquire()获取资源–5
Thread-5,semaphore.release()释放资源–5
Thread-4, semaphore.acquire()获取资源–4
Thread-4,semaphore.release()释放资源–4
Thread-6, semaphore.acquire()获取资源–6
Thread-6,semaphore.release()释放资源–6
Thread-7, semaphore.acquire()获取资源–7
Thread-7,semaphore.release()释放资源–7
Thread-9, semaphore.acquire()获取资源–9
Thread-9,semaphore.release()释放资源–9
Thread-8, semaphore.acquire()获取资源–8
Thread-8,semaphore.release()释放资源–8
在没有释放资源前,只有五个线程可以获取资源,其他线程都进入队列阻塞。当线程获取资源,执行完业务代码释放资源,则每个线程都可以获取资源,无需阻塞。
Semaphore
中也有一个内部类Sync
,Sync
继承自AbstractQueuedSynchronizer
,所以核心代码都在Sync
中。从构造函数看出,Sync
还有两个子类NonfairSync
和FairSync
,说明Semaphore
实现的共享锁区分公平性。
public class Semaphore implements java.io.Serializable {
private static final long serialVersionUID = -3222578661600680210L;
/** All mechanics via AbstractQueuedSynchronizer subclass */
private final Sync sync;
/**
-
Synchronization implementation for semaphore. Uses AQS state
-
to represent permits. Subclassed into fair and nonfair
-
versions.
*/
abstract static class Sync extends AbstractQueuedSynchronizer {
… …
}
public Semaphore(int permits) {
sync = new NonfairSync(permits);
}
public Semaphore(int permits, boolean fair) {
sync = fair ? new FairSync(permits) : new NonfairSync(permits);
}
}
Semaphore提供了可中断获取资源许可(Semaphore#acquire()
),不可中断获取资源许可(Semaphore#acquireUninterruptibly()
),尝试获取资源许可(Semaphore#tryAcquire()
),超时可中断获取资源许可(Semaphore#tryAcquire(long, java.util.concurrent.TimeUnit)
)。底层代码调用的都是AQS中共享模式获取锁的模板方法,故只需要看看tryAcquireShared
在Semaphore
中的实现。
//1.可中断获取资源许可
public void acquire() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
//2.可中断获取permits个资源许可
public void acquire(int permits) throws InterruptedException {
if (permits < 0) throw new IllegalArgumentException();
sync.acquireSharedInterruptibly(permits);
}
//3.不可中断获取资源许可
public void acquireUninterruptibly() {
sync.acquireShared(1);
}
//4.不可中断获取permits个资源许可
public void acquireUninterruptibly(int permits) {
if (permits < 0) throw new IllegalArgumentException();
sync.acquireShared(permits);
}
//5.尝试获取资源许可,获取成功返回true
public boolean tryAcquire() {
return sync.nonfairTryAcquireShared(1) >= 0;
}
//6.尝试获取permits个资源许可,获取成功返回true
public boolean tryAcquire(int permits) {
if (permits < 0) throw new IllegalArgumentException();
return sync.nonfairTryAcquireShared(permits) >= 0;
}
//7.超时可中断获取资源许可,获取失败进入队列阻塞一段时间,超时还未获取返回false
public boolean tryAcquire(long timeout, TimeUnit unit)
throws InterruptedException {
return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
}
//8.超时可中断获取permits个资源许可,获取失败进入队列阻塞一段时间,超时还未获取返回false
public boolean tryAcquire(int permits, long timeout, TimeUnit unit)
throws InterruptedException {
if (permits < 0) throw new IllegalArgumentException();
return sync.tryAcquireSharedNanos(permits, unit.toNanos(timeout));
}
tryAcquireShared
Semaphore中获取资源许可有公平锁和非公平锁之分。
Semaphore.NonfairSync#tryAcquireShared
NonfairSync
中的tryAcquireShared
调用了Semaphore.Sync
中已经实现好的nonfairTryAcquireShared
。
static final class NonfairSync extends Sync {
private static final long serialVersionUID = -2694183684443567898L;
NonfairSync(int permits) {
super(permits);
}
protected int tryAcquireShared(int acquires) {
return nonfairTryAcquireShared(acquires);
}
}
获取资源许可,就是对state做减法,remaining =当前许可量—获取的许可量,remaining >= 0
即可以CAS
修改state
资源许可数,获取成功返回remaining
资源许可剩余量。CAS
修改state失败会不断自旋。
//java.util.concurrent.Semaphore.Sync#nonfairTryAcquireShared
final int nonfairTryAcquireShared(int acquires) {
for (;😉 {
//获取可用资源许可量
int available = getState();
//计算可用资源许可剩余量
int remaining = available - acquires;
//remaining <0 说明资源许可耗尽
//remaining >= 0 可继续获取资源许可cas
if (remaining < 0 ||
compareAndSetState(available, remaining))
//返回剩余许可量
return remaining;
}
}
Semaphore.FairSync#tryAcquireShared
FairSync
中tryAcquireShared
与NonfairSync
唯一的区别就是FairSync
中首先会判断当前同步队列中是否有线程也在等待获取资源许可,有则获取失败返回-1,没有则继续获取许可。CAS
修改state失败会不断自旋。
static final class FairSync extends Sync {
private static final long serialVersionUID = 2014338818796000944L;
FairSync(int permits) {
super(permits);
}
protected int tryAcquireShared(int acquires) {
for (;😉 {
//判断同步队列中是否有线程在等待获取资源许可,有则获取失败返回-1
if (hasQueuedPredecessors())
return -1;
//同步队列中没有线程在等待,则可以继续获取许可,同非公平下的获取许可
int available = getState();
int remaining = available - acquires;
if (remaining < 0 ||
compareAndSetState(available, remaining))
return remaining;
}
}
}
最后
各位读者,由于本篇幅度过长,为了避免影响阅读体验,下面我就大概概括了整理了
|
compareAndSetState(available, remaining))
return remaining;
}
}
}
最后
各位读者,由于本篇幅度过长,为了避免影响阅读体验,下面我就大概概括了整理了
[外链图片转存中…(img-6CytMWL4-1715811226174)]
[外链图片转存中…(img-4J6pBP8V-1715811226175)]
[外链图片转存中…(img-MpiG3mUE-1715811226175)]
[外链图片转存中…(img-YLTIuK2D-1715811226175)]