目录
1 重入锁概述
ReentrantLock加锁解锁就是AQS实现的Sync同步工具类
在ReentrantLock中,state如果等于0,表示资源空闲;如果>0表示资源被占用,具体数值表示资源被占用次数,即重入次数
2 非公平锁加锁
final void lock() {
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
加锁的时候不会直接获取资源,而是再查看当前资源占用状态,如果没有占用则直接占用,这是非公平的体现;否则才进行获取资源过程
上篇文章中已经分析了acquire方法的执行过程,现在看一下acquire方法中第一步tryAcquire在非公平锁中的具体实现
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
// 这里再获取一下state资源状态,如果没有被占用则进行cas争取
if (c == 0) {
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
// 如果当前线程就是被占用线程则把state状态+1
int nextc = c + acquires;
if (nextc < 0) // overflow
// 这里可以看到可重入锁也不是可以无限重入,最大次数是Integer.MAX_VALUE;
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
3 公平锁加锁
final void lock() {
acquire(1);
}
可以看到与非公平锁的区别是直接进行获取资源,而不是先检查当前资源状态,这里在看一下公平锁中tryAcquire方法的实现
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
// 当前state没有资源占用并且队列中没有等待的线程才进行cas抢锁,确保公平性
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;
}
4 释放锁
public void unlock() {
sync.release(1);
}
上篇文章中已经分析了release方法执行过程,这里看一下tryRelease方法在ReentrantLock中的具体实现
protected final boolean tryRelease(int releases) {
if (!isHeldExclusively())
// 如果不是占用资源的线程释放锁直接抛异常
throw new IllegalMonitorStateException();
// state状态-releases
int nextc = getState() - releases;
boolean free = exclusiveCount(nextc) == 0;
if (free)
// 如果state==0表示没有线程占用资源,设置当前占用线程为空
setExclusiveOwnerThread(null);
setState(nextc);
return free;
}
5 公平锁和非公平锁比较
- 分析源码可知公平锁可以保证线程先到先执行,而非公平锁不能
- 非公平锁性能高于公平锁性能。
首先非公平锁更多次的执行CAS能更充分的利用cpu的时间片,尽量的减少cpu空闲的状态时间,降低线程进入队列等待执行的可能。
其次在恢复一个被挂起的线程与该线程真正运行之间存在着严重的延迟。