前言
上一篇咱们分析了ReentrantLock公平锁的获取和释放的源码,本篇再看非公平锁的源码就轻松多了,上一篇没看的建议先去看公平锁的源码分析。
1、获取非公平锁
下面是非公平锁获取锁的源码,是在ReentrantLock.java的NonfairSync类中。
final void lock() {
//通过CAS判断"锁"是不是空闲状态
if (compareAndSetState(0, 1))
//设置“当前线程”为“锁”的持有者
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
acquire()在AbstractQueuedSynchronizer(AQS)抽象类中定义的,它的源码如下:
//注意,acquire方法中,tryAcquire方法是由公平锁类和非公平锁类自己实现的
//addWaiter、acquireQueued、selfInterrupt方法是由AQS自己实现的
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
1.1、tryAcquire方法
非公平锁的tryAcquire()在ReentrantLock.java的NonfairSync类中实现,源码如下:
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
nonfairTryAcquire()在ReentrantLock.java的Sync类中实现,源码如下:
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
//细心的同学可能已经发现了,这里比公平锁的少了一行代码
//少了的那行代码是:!hasQueuedPredecessors(),判断自己是不是等待队列的第一个
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;
}
2、释放非公平锁
释放非公平锁和释放公平锁是一样的,这里不重复说明,忘记了的,可以再回去看看公平锁的释放方法。
3、公平锁和非公平锁的区别
- 公平锁和非公平锁的区别,是在获取锁的机制上。
- 公平锁只有当前线程在队列的头部且锁是空闲的才能获取锁。
- 非公平锁只要锁是空闲的,当前线程就可以直接获取锁。
- 非公平锁在尝试获取锁失败后,才会像公平锁一样,在队列排队获取锁。
结束语
本篇结束了非公平锁的源码分析,并且总结了“独占锁”ReentrantLock公平锁和非公平锁的区别,下一篇将分析共享锁ReentrantReadWriteLock。