目录
1. ReentrantLock 实现Lock接口(实际就是锁)
1.ReentrantLock
1. ReentrantLock 实现Lock接口(实际就是锁)
//Lock源码解读
public interface Lock {
/**
* 加锁
*/
void lock();
/**
* 加锁并响应中断
*/
void lockInterruptibly() throws InterruptedException;
/**
* 只有空闲的才能获取锁,返回boolean值
*/
boolean tryLock();
/**
*在指定时间内获取锁,可以响应中断
*/
boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
/**
*解锁
*/
void unlock();
/**
* 返回condition对象
*/
Condition newCondition();
}
1.2 内部类Sync类的源码解析
ReentrantLock类的内部共存咋iSync,NonfairSync,FairSync三个类,NonfairSync与FairSync类继承自Sync,Sync继承自 AbstractQueuedSynchronizer
//重入锁基础的同步控制器
abstract static class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = -5179523762034025860L;
/**
* 加锁方法,由Sync的子类FairSync和NonfairSync实现
*/
abstract void lock();
/**
* 非公平方式加锁
*/
final boolean nonfairTryAcquire(int acquires) {
//当前线程
final Thread current = Thread.currentThread();
//当前线程的状态,即AQS中的state状态
int c = getState();
//c等于0表示没有线程持有state状态
if (c == 0) {
//CSA修改state状态,如果CAS成功,即加锁成功
if (compareAndSetState(0, acquires)) {
//设置当前线程已独占的方式持有锁
setExclusiveOwnerThread(current);
//返回加锁成功
return true;
}
}
//如果c不等于0,表示此时锁被占有
//如果当前的线程就是锁的持有者
else if (current == getExclusiveOwnerThread()) {
//发生重入,增加重入的次数
int nextc = c + acquires;
如果nextc小于0,即发生了int类型的溢出
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
//设置state状态
setState(nextc);
//返回重入加锁成功
return true;
}
//返回加锁失败
return false;
}
//对类AQS中的tryRelease()重写
protected final boolean tryRelease(int releases) {
//获取state状态,减去要释放的资源releases
int c = getState() - releases;
//如果当前线程不是锁的拥有者
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
//是否完全释放锁
boolean free = false;
//如果c等于0
if (c == 0) {
//表示已经完全释放,没有任何线程持有锁
free = true;
//将锁拥有者置为null
setExclusiveOwnerThread(null);
}
setState(c);
//返回锁是否 被完全释放
return free;
}
//对类AQS的isHeldExclusively重写
protected final boolean isHeldExclusively() {
// 校验当前线程是否与持有锁的线程相等
return getExclusiveOwnerThread() == Thread.currentThread();
}
//返回一个AQS内部类ConditionObject对象
final ConditionObject newCondition() {
return new ConditionObject();
}
// 返回锁的持有者
final Thread getOwner() {
return getState() == 0 ? null : getExclusiveOwnerThread();
}
//返回重如锁的进入次数
final int getHoldCount() {
//如果isHeldExclusively为true
//这说明当前线程是锁的持有者,返回state
//否则返回0
return isHeldExclusively() ? getState() : 0;
}
//是否已经被加锁
final boolean isLocked() {
return getState() != 0;
}
/**
* 通过流反序列化对象
*/
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
s.defaultReadObject();
setState(0); // reset to unlocked state
}
}
1.3 内部类FairSync(公平锁)源码解析
/**
* FairSync 继承Sync,实现公平锁
*/
static final class FairSync extends Sync {
private static final long serialVersionUID = -3000897897090466540L;
//加锁
final void lock() {
//调用父类方法实现加锁
acquire(1);
}
/**
* 实现父类tryAcquire方法 重写
*/
protected final boolean tryAcquire(int acquires) {
//当前线程
final Thread current = Thread.currentThread();
//锁的状态
int c = getState();
//c等于0,表示未被锁定
if (c == 0) {
//hasQueuedPredecessors是父类的方法
//用于查询是否有等待锁的时间比当前线程更长的线程
//如果没有优先级比当前线程等待更久的线程
//则通过CAS设置state状态从0变成acquires
//如果cas设置成功,说明线程加锁成功
//设置锁的持有者为当前线程
if (!hasQueuedPredecessors() &&
compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
//加锁成功
return true;
}
}
//如果c不等于0
//判断当前线程是不是锁的持有者
//如果是,则发生重进入
else if (current == getExclusiveOwnerThread()) {
//nextc等于c加acquires
int nextc = c + acquires;
//c<0发生溢出
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc);
//返回加锁成功
return true;
}
//返回加锁失败
return false;
}
}
1.4 内部类NonFairSync(非公平锁)源码解析
/**
*非公平锁
*/
static final class NonfairSync extends Sync {
private static final long serialVersionUID = 7316153563782823691L;
/**
*加锁
*/
final void lock() {
//cas使state从0变成1
//如果cas成功,则将当前线程设置为锁的持有者
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
//如果cas失败,则调用父类AQS中的acquire方法进行加锁
acquire(1);
}
//实际是调用子类的nonfairTryAcquire方法
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
}
2 ReentrantLock公平锁加锁及解锁过程
ReentrantLock的Lock方法调用Sync的lock方法,Sync有公平锁和非公平锁两种情况
加锁过程:
2.1:进入FairSync的Lock方法
final void lock(){
acquire(1);
}
2.2:调用父类AQS的acquire方法
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
3:父类AQS的accquire方法调用tryAcquire方法,需要子类实现
protected boolean tryAcquire(int arg) {
throw new UnsupportedOperationException();
}
4:tryAcquire方法在公平锁中的实现,
请参考上方1.3 内部类FairSync(公平锁)源码解析的tryAcquire()方法
3. 解锁过程:
3.1:ReentrantLock解锁方法如下:
public void unlock() {
sync.release(1);
}
3.2:调用父类AQS的release()方法
public final boolean release(int arg) {
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}
3.3:tryrelease()方法需要子类实现
请参考1.2 内部类Sync类的源码解析的tryrelease()方法
3.21 ReentrantLock非公平锁加锁及解锁过程
3.22:非公平锁的加锁入口与公平锁加锁一样都是lock方法,只是调用的Sync对的引用不同
public void lock() {
sync.lock();
}
3.23:NonfairSync中对lock方法实现如下,细节请参考1.3 内部类NonFairSync(非公平锁)源码解析
final void lock() {
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
3.24:与公平锁fairSync中的lock方法不同的是,NonfairSync中对lock方法直接进行CAS操作,如果CAS成功就设置锁的持有者为当前线程--非公平 的体现
final void lock(){
acquire(1);
}
3.25:如果NonfairSync中对lock方法CAS失败,这说明有竞争者,将会进入父类CAS中的acquire方法
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
3.26:tryAcquire依旧需要子类实现,NonfairSync中对tryAcquire方法实现如下
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
3.27:NonfairSync中对tryAcquire调用的NonfairSync方法是父类中的方法,请参考1.2 内部类Sync类的源码解析中的NonfairSync方法
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
3.28:与公平锁不同是,公平锁多加了hasQueuedPredecessors方法的调用
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (!hasQueuedPredecessors() &&
compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
}
hasQueuedPredecessors方法是判断等待队列中是否存在当前线程先入队的线程,公平锁加锁需要先对等待队列的线程做出让步,先来后到,非公平锁不管先来后到,直接加锁;如果NonfairSync方法返回false,即非公平锁加锁失败,回到AQS中的accquire方法
4. ReentrantLock的公平锁VS非公平锁
两者之间没有具体的好坏之分,根据使用场景选择对应的锁技术
公平锁---侧重的是公平性
非公平锁--侧重的是并发性
非公平锁对锁的竞争是抢占式的(队列中的线程除外)线程在进入等待队列前进行两次尝试,这大大增大了获取锁的机会,这种好处提现在两个方面:
1:线程不比加入等待队列就可以获得锁,不仅免去了构造节点加入队列繁琐的操作,同时也省去了线程阻塞唤醒的开销,线程阻塞和唤醒涉及到线程上下文的切换和操作系统调用,是非常耗时的,在高并发情况下如果线程持有锁的时间非常短,短到线程入队阻塞的过程超过线程持有并释放的时间开销,那么这种抢占式特性对并发的提升更加明显
2:减少CAS竞争,如果线程必须要加入阻塞队列才能获取锁,那入队时CAS竞争将异常激烈CAS操作虽然不会导致失败线程挂起但是不断失败重试导致的对CPU的浪费也不能忽视
2.Semaphore
主要做并发控制;控制并发提升性能
Semaphore底层是基于AbstractQeuedSynchronizer来实现的所以Semaphore的数据结构也是依托于AQS的数据结构
1.1 Semaphore内部类Sync源码解析
/**
* 内部类Sync继承自AQS
*/
abstract static class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = 1192457210091910933L;
//构造器
Sync(int permits) {
setState(permits);
}
//获得许可
final int getPermits() {
return getState();
}
//共享模式下非公平方式获取资源
final int nonfairTryAcquireShared(int acquires) {
for (;;) {
//获取许可
int available = getState();
//剩余许可
int remaining = available - acquires;
//许可小于0或者CAS设置状态成功
if (remaining < 0 ||
compareAndSetState(available, remaining))
//返回remaining
return remaining;
}
}
//共享模式下释放资源
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");
//如果cas成功
if (compareAndSetState(current, next))
//返回true
return true;
}
}
//减少许可数
final void reducePermits(int reductions) {
for (;;) {
//获取许可
int current = getState();
//剩余可用的许可
int next = current - reductions;
if (next > current) // underflow
throw new Error("Permit count underflow");
//cas成功
if (compareAndSetState(current, next))
return;
}
}
//获取并返回所有许可
final int drainPermits() {
for (;;) {
//获取许可数
int current = getState();
//如果current等于0或者cas成功
if (current == 0 || compareAndSetState(current, 0))
return current;
}
}
}
Sync类的属性相对简单,只有一个版本号
方法名 | 左用 |
| 获取许可 |
| 共享模式下非公平策略获取 |
| 共享模式下进行释放 |
| 根据指定的缩减减少可用许可的数目 |
| 获取并返回可用的所有许可 |
1.2 NonfairSync源码解析
NonfairSync类继承自Sync类,表示采用非公平策略获取资源,其中有一个tryAcquireShared方法,重写AQS的tryAcquireShared方法:
/**
* 非公平版本
*/
static final class NonfairSync extends Sync {
private static final long serialVersionUID = -2694183684443567898L;
NonfairSync(int permits) {
super(permits);
}
//共享模式下获取资源
protected int tryAcquireShared(int acquires) {
//调用父类Sync中的NonfairSyncTryAcquireShared方法
return nonfairTryAcquireShared(acquires);
}
}
1.3 FairSync 源码解析
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;
//获取state状态
int available = getState();
//剩余时间
int remaining = available - acquires;
//如果剩余许可小于0或者cas成功
if (remaining < 0 ||
compareAndSetState(available, remaining))
return remaining;
}
}
}
2.1Semaphore类的非公平模式获取许可源码解析
public void acquire() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
public void acquire(int permits) throws InterruptedException {
if (permits < 0) throw new IllegalArgumentException();
sync.acquireSharedInterruptibly(permits);
}
3:acquire调用父类AQS中的AcquireSharedinterruptbly方法
public final void acquireSharedInterruptibly(int arg)
throws InterruptedException {
//如果线程被中断
if (Thread.interrupted())
throw new InterruptedException();
//tryAcquireShared方法需要子类实现
//如果tryAcquireShared方法返回小于0
//则获取资源失败
if (tryAcquireShared(arg) < 0)
//调用doAcquireSharedInterruptibly方法
doAcquireSharedInterruptibly(arg);
}
4:AcquireSharedinterruptbly方法调用的tryAcquireShared方法在非公平模式下的实现如下
protected int tryAcquireShared(int arg) {
throw new UnsupportedOperationException();
}
5:tryAcquireShared方法调用的NonfairTryAcquireShared方法如下:详细参考:1.1 Sync源码解析
final int nonfairTryAcquireShared(int acquires) {
for (;;) {
int available = getState();
int remaining = available - acquires;
if (remaining < 0 ||
compareAndSetState(available, remaining))
return remaining;
}
}
6:tryAcquireShared方法返回小于0,则获取资源失败,执行doAcquireSharedInterruptibly方法
private void doAcquireSharedInterruptibly(int arg)
throws InterruptedException {
final Node node = addWaiter(Node.SHARED);
boolean failed = true;
try {
for (;;) {
final Node p = node.predecessor();
if (p == head) {
int r = tryAcquireShared(arg);
if (r >= 0) {
setHeadAndPropagate(node, r);
p.next = null; // help GC
failed = false;
return;
}
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
throw new InterruptedException();
}
} finally {
if (failed)
cancelAcquire(node);
}
}
3.1 非公平模式释放许可资源源码解析
1:释放许可
public void release() {
sync.releaseShared(1);
}
public void release(int permits) {
if (permits < 0) throw new IllegalArgumentException();
sync.releaseShared(permits);
}
2:release方法调用AQS中的releaseShared方法
public final boolean releaseShared(int arg) {
if (tryReleaseShared(arg)) {
doReleaseShared();
return true;
}
return false;
}
3:其中tryReleaseShared需要子类实现
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;
}
}
4:如果tryReleaseShared返回true将执行都releaseShared方法,
private void doReleaseShared() {
for (;;) {
Node h = head;
if (h != null && h != tail) {
int ws = h.waitStatus;
if (ws == Node.SIGNAL) {
if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0))
continue; // loop to recheck cases
unparkSuccessor(h);
}
else if (ws == 0 &&
!compareAndSetWaitStatus(h, 0, Node.PROPAGATE))
continue; // loop on failed CAS
}
if (h == head) // loop if head changed
break;
}
}
4. 公平模式获取许可源码分析
公平模式获取许可的acquire方法与非公平模式下获取许可是一样的,不同的是tryAcquireShared方法的实现;与非公平模式相比,公平模式多了hasQueuedPredecessors
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;
}
}
}
public final boolean hasQueuedPredecessors() {
// The correctness of this depends on head being initialized
// before tail and on head.next being accurate if the current
// thread is first in queue.
Node t = tail; // Read fields in reverse initialization order
Node h = head;
Node s;
return h != t &&
((s = h.next) == null || s.thread != Thread.currentThread());
}
公平模式释放许可和非公平模式是一样的