java模板模式与AQS实现( 四 )


这个方法是AQS类的方法,不可复写,目的在于查看同步队列中有无前驱节点,如果没有前驱,则说明当前线程前边没有别的线程尝试获取资源,当前线程才会进行CAS操作尝试获取资源 。如果有前驱,当前线程不会尝试获取资源,而是执行以及后续操作,主动进入同步队列 。
所以,非公平锁和公平锁区别就在于,当某线程执行时,非公平锁不关心同步队列,直接尝试获取资源,成功了就获取到资源了,失败了才进入到同步队列,而公平锁首先会检查同步队列是不是有节点,如果没有才尝试获取资源,如果有节点则直接进入同步队列排队 。通俗一点就是非公平锁没素质,直接插队,公平锁直接排队,到我了才获取资源 。
AQS在jdk中的应用之二:(信号量)
是用来控制并发线程数的一种机制 。先看下java的注释:
* A counting semaphore.Conceptually, a semaphore maintains a set of* permits.Each {@link #acquire} blocks if necessary until a permit is* available, and then takes it.Each {@link #release} adds a permit,* potentially releasing a blocking acquirer.* However, no actual permit objects are used; the {@code Semaphore} just* keeps a count of the number available and acts accordingly.** Semaphores are often used to restrict the number of threads than can* access some (physical or logical) resource.
大意是持有一些许可,这些许可并不是真正的对象,而只是一个数字在记录,它可以用来限制并发的线程数 。
比如有50个线程,但是同时并发执行的线程仅能有10个,其他线程处于阻塞状态 。换一种方式解释,就是说,仅有10个资源,却有50个线程想获取资源,当然只能一部分一部分地获取,比如0~9号线程获取到了资源,开始执行各自的逻辑,假如3号线程执行完毕,会释放一个资源,同时唤醒阻塞队列第一个节点,使得该节点的线程得以访问资源 。这就是共享锁啊!查看java源码发现,确实是基于AQS实现的共享锁 。
final int getPermits() {return getState();}final int nonfairTryAcquireShared(int acquires) {for (;;) {int available = getState();int remaining = available - acquires;if (remaining < 0 ||compareAndSetState(available, remaining))return remaining;}}protected final boolean tryReleaseShared(int releases) {for (;;) {int current = getState();int next = current + releases;if (next < current) // overflowthrow new Error("Maximum permit count exceeded");if (compareAndSetState(current, next))return true;}}
可以看到,(许可)其实就是AQS的state变量,在这里指代资源数量,与可重入锁一样,也区分公平和非公平,原理也一致 。这里贴的是非公平锁的代码,可以看到方法试图获取资源,获取到则占用,获取不到则进入AQS的逻辑 。为释放资源,都是对state这个数的操作,与前边描述一致,不再赘述 。
基于AQS的自定义锁的实现
自定义锁的实现大体流程:确定实现独占还是共享锁 --> 继承AQS -->实现和方法;
如下自定义了一个共享锁,其实是造了个的简单轮子,支持自定义资源个数:
public class NSourceLock implements Lock {private Sync sync;public NSourceLock() {sync = new Sync(1);}public NSourceLock(long sourceCount) {sync = new Sync(sourceCount);}/*** 写成静态内部类,继承AQS模板类*/private static final class Sync extends AbstractQueuedLongSynchronizer {Sync(long sourceCount) {if (sourceCount < 1) {throw new IllegalStateException("source should be no less than 1");}//调用AQS方法,设置资源数目setState(sourceCount);}@Overrideprotected long tryAcquireShared(long arg) {//自旋while (true) {long cur = getState(); //当前资源数,注意state字段是volatile修饰,这里保证可见性long newCount = cur - arg; //请求多少资源,arg为请求资源数if (newCount