可重入锁,在一个线程中可多次获取到该锁;主要通过AQS实现;通过使用ReentrantLock可以比synchronized更加灵活,ReentrantLock并不是真正的通过同步加锁实现的,性能比synchronized好;
一般情况下ReentrantLock的使用过程
//先获取锁
lock.lock();
try {
... //业务逻辑
} finally{
//finally块进行锁的释放,保证获取到的锁被释放
lock.unlock();
}
AQS通过state属性来控制所状态
//AQS的静态代码块
static {
try {
//获取到state的offset,供后面的CAS操作用
stateOffset = unsafe.objectFieldOffset
(AbstractQueuedSynchronizer.class.getDeclaredField("state"));
headOffset = unsafe.objectFieldOffset
(AbstractQueuedSynchronizer.class.getDeclaredField("head"));
tailOffset = unsafe.objectFieldOffset
(AbstractQueuedSynchronizer.class.getDeclaredField("tail"));
waitStatusOffset = unsafe.objectFieldOffset
(Node.class.getDeclaredField("waitStatus"));
nextOffset = unsafe.objectFieldOffset
(Node.class.getDeclaredField("next"));
} catch (Exception ex) { throw new Error(ex); }
}
而锁定操作通过CAS操作AQS的state
//AQS的state属性定义,用volatile修饰(内存可见性保证)
private volatile int state;
//AQS的CAS操作
protected final boolean compareAndSetState(int expect, int update) {
//通过unsafe的CAS操作state
return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}
ReentrantLock默认的锁方式
public ReentrantLock() {
sync = new NonfairSync();
}
看看ReentrantLock#lock()是如何实现(NonfairLock)
public void lock() {
//因为ReentrantLock的默认构造方法把sync初始化为NonfairLock,所以这里的lock是采用非公平锁的lock
sync.lock();
}
接着看NonfairLock#lock()
final void lock() {
//非公平锁的lock一来就先获取锁(AQS通过维护state值来实现锁,0表示未锁定)
//通过CAS来实现,具体看上面的compareAndSetState实现解析
if (compareAndSetState(0, 1))
//state状态设置成功,说明可以马上拿到资源,直接将当前的线程设置为锁的独占线程
//ReentrantLock采用独占锁方式
//重入的时候会用来比较是否同一个线程
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
}
public final void acquire(int arg) {
//调用NonfairLock的tryAcquire,
//NonfairLock的tryAcquire再调用Sync#nonfairTryAcquire获取锁,
//如果获取到锁,继续执行程;
//获取不到锁,继续调用AbstractQueuedSynchronizer#acquireQueued,
//如果有中断操作,对当前线程interrupt
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
//传进来的acquires为1
final boolean nonfairTryAcquire(int acquires) {
// 获取当前线程对象
final Thread current = Thread.currentThread();
// 获取AQS的state
int c = getState();
//如果是0表示能获取到锁
if (c == 0) {
//通过CAS获取锁
if (compareAndSetState(0, acquires)) {
//获取到锁,将当前线程设置为锁的独占线程,返回true表示获取到锁
setExclusiveOwnerThread(current);
return true;
}
}
//state不为0(表示已经有线程获取到该锁),
//那么判断当前线程和持有锁的独占线程是否为同一个线程,
//同一个线程可以重入
else if (current == getExclusiveOwnerThread()) {
//将当前的state加上acquires,这里为1
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
//设置state值,因为state为volatile,所有内存可见
setState(nextc);
//返回true,表示获取到锁
return true;
}
return false;
}
private Node addWaiter(Node mode) {
//新建一个node,以当前线程作为Node的thread
Node node = new Node(Thread.currentThread(), mode);
Node pred = tail;
//如果tailNode不为空
if (pred != null) {
//将新建的node的prev指向到tail
node.prev = pred;
// 通过CAS将新建的node设置为tail
if (compareAndSetTail(pred, node)) {
// 将之前的tailNode的next指向新建的node
//结合前面的操作,意思就是将新建的node插入到队尾
pred.next = node;
return node;
}
}
//如果不能将node插入到队尾,那么就调用AQS#enq
enq(node);
return node;
}
private final boolean compareAndSetTail(Node expect, Node update) {
//tailOffset为tailNode的offset,在AQS静态初始化块中初始化的
return unsafe.compareAndSwapObject(this, tailOffset, expect, update);
}
private Node enq(final Node node) {
//采用自旋的方式将node设置为tail
for (;;) {
Node t = tail;
//如果队尾node为空,那么表示队列里没有node
if (t == null) { // Must initialize
//通过CAS将一个新的node作为head,然后将tail设置成head一样的node,
//即队列只有一个元素
if (compareAndSetHead(new Node()))
tail = head;
} else {
//否则将当前的node设置为队尾
node.prev = t;
if (compareAndSetTail(t, node)) {
t.next = node;
return t;
}
}
}
}
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
//采用自旋方式,拿锁
for (;;) {
//获取传入node的前一个node
final Node p = node.predecessor();
//如果前一个node为head node,那么尝试获取锁
if (p == head && tryAcquire(arg)) {
// 获取到锁以后,将head设置为传入node,并将node的thread和prev设置为null
setHead(node);
p.next = null; // help GC
//failed设置为false,finally中不需要调用cancelAcquire
failed = false;
//终止状态返回false
return interrupted;
}
// head不为传入的node的前一个node,或者获取不到锁
// 调用AQS#shouldParkAfterFailedAcquire和AbstractQueuedSynchronizer#parkAndCheckInterrupt,
// 如果中间有被interrupt过,那么interrupted状态为true
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
//通过自旋如果获取锁失败,取消获取锁操作
cancelAcquire(node);
}
}
private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
//获取prev node的等待状态
int ws = pred.waitStatus;
if (ws == Node.SIGNAL)
//如果等待状态SIGNAL,直接返回true
return true;
if (ws > 0) {
//一直找到waitStatus为非CANCEL的节点,
//并将找到的节点的next设置node,也就是将CANCEL的节点抛弃了
do {
node.prev = pred = pred.prev;
} while (pred.waitStatus > 0);
pred.next = node;
} else {
// 否则将pred node的状态设置为SIGNAL
compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
}
return false;
}
private final boolean parkAndCheckInterrupt() {
LockSupport.park(this); //调用park()使线程进入waiting状态
return Thread.interrupted(); //如果被notify,查看自己是不是被中断的
}
前面讲的都lock的过程,接下来看看unlock
public final boolean release(int arg) {
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}
release通过Sync的tryRelease来释放锁方法protected final boolean tryRelease(int releases) {
int c = getState() - releases;
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
//如果c为0,表示当前锁释放掉以后,不再持有锁,将独占锁线程设置为null
if (c == 0) {
//如果锁释放了,且当前线程不持有锁,那么返回true,否则返回false
free = true;
setExclusiveOwnerThread(null);
}
//设置state为c,如果c大于0,表示c还持有独占锁
setState(c);
return free;
}
想要使用公平锁,则需要在创建ReentrantLock的时候传入参数,new ReentrantLock(true);
公平锁的lock过程:
final void lock() {
//直接调用AQS的acquire方法
acquire(1);
}
//调用基本跟非公平锁类似,只是tryAcquire调用的是FairSync的方法
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
//只有在1、队列中没有等待锁且锁未被其他线程持有
//2、或者当前线程为已持有锁的线程时获取锁成功
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;
}