文章目录
前言
了解ReentrantLock的原理和底层实现
一、ReentrantLock是如何实现的?
ReentrantLock 主要利用CAS 和 AQS队列实现,并且支持公平锁和非公平锁。
CAS:Compare and Swap,比较并交换。在java中,CAS主要由Unsafe类通过JIN调用CPU底层代码实现。
CAS有三个参数:内存值V、预期值A、新值B。当且仅当,预期值A和内存值V相同时,将内存值修改为B,否则不做修改。
关于AQS,参见文章AQS队列
二、lock 和 unlock的过程分析
2.1 ReentrantLock的两个构造器
public ReentrantLock() {
sync = new NonfairSync();
}
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
默认构造器会将其实例化为NonfairSync对象,即非公平锁,而带参数的构造器可以指定使用公平锁还是非公平锁。
2.2 lock过程
NonfairSync.lock
final void lock() {
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
非公平锁的lock方法中,首先是一个CAS操作,判断state是否是0,即当前锁是否被其他线程占用了;如果是0,则设置为1,且设置当前线程为独占线程。这里CAS操作避免了并发操作的问题。
这里也是第一处体现非公平锁:如果此处占用锁的线程刚刚好释放锁,则当前线程可以直接获取锁,而无需排队,相当于直接“插队”。
若此处没有设置成功,即没有获取锁,则会执行acquire()方法。
acquire()
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
第一步是调用tryAcquire()方法,尝试获取锁。
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
//状态为0,没有线程占用锁