ReentrantLock是常用的控制并发安全的lock实现了,里面主要包含lock()加锁方法,unlock()释放锁的方法,内部又分为公平锁和非公平锁,简单看下怎么实现的吧
简单提下lock自己平时怎么用的
// 这里的lock注意,需要用的是同一个lock才能保证并发安全
ReentrantLock reentrantLock = new ReentrantLock();
reentrantLock.lock();
// 自己业务代码放在这里
reentrantLock.unlock();
Sync 内部类
abstract static class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = -5179523762034025860L;
/**
* Performs non-fair tryLock. tryAcquire is implemented in
* subclasses, but both need nonfair try for trylock method.
*/
@ReservedStackAccess
final boolean nonfairTryAcquire(int acquires) {
// 非公平锁的加锁
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
// state为0 的时候代表没人持有,那么就cas尝试加锁
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;
}
@ReservedStackAccess
protected final boolean tryRelease(int releases) {
// 释放锁
int c = getState() - releases;
// 不是自己持有的话,异常
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
// 如果为0,证明释放了
if (c == 0) {
free = true;
setExclusiveOwnerThread(null);
}
// 更新state
setState(c);
return free;
}
// 是不是自己持有的锁
protected final boolean isHeldExclusively() {
// While we must in general read state before owner,
// we don't need to do so to check if current thread is owner
return getExclusiveOwnerThread() == Thread.currentThread();
}
//
final ConditionObject newCondition() {
return new ConditionObject();
}
// Methods relayed from outer class
// 获取持有者,如果没人持有就是null
final Thread getOwner() {
return getState() == 0 ? null : getExclusiveOwnerThread();
}
// 被持有了多少次
final int getHoldCount() {
return isHeldExclusively() ? getState() : 0;
}
// 是不是正在锁
final boolean isLocked() {
return getState() != 0;
}
/**
* Reconstitutes the instance from a stream (that is, deserializes it).
*/
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
s.defaultReadObject();
setState(0); // reset to unlocked state
}
}
Sync 主要定义了锁的一些常用操作,可以看到它继承了AbstractQueuedSynchronizer,这里才是重要的,这里后面单独文章分析下,然后公平锁和非公平锁继承Sync,差别就在于加锁这点
/**
* Sync object for non-fair locks
*/
static final class NonfairSync extends Sync {
private static final long serialVersionUID = 7316153563782823691L;
protected final boolean tryAcquire(int acquires) {
// 非公平锁,直接使用的父类的
return nonfairTryAcquire(acquires);
}
}
/**
* Sync object for fair locks
*/
static final class FairSync extends Sync {
private static final long serialVersionUID = -3000897897090466540L;
/**
* Fair version of tryAcquire. Don't grant access unless
* recursive call or no waiters or is first.
*/
@ReservedStackAccess
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;
}
}
总结
可以看到ReentrantLock里面主要就是内部类提供了公平锁和非公平锁,然后Sync继承了AbstractQueuedSynchronizer 使用其方法,ReentrantLock 主要提供了加锁和解锁的方法,分为公平锁和非平平锁,默认非公平锁,两者的区别在于,公平锁在加锁之前会判断是不是又线程在队列里面等待,有等待的就自己排队,无等待者的话自己尝试加锁,非公平锁是看到锁处于无锁,就会cas尝试下加锁,这就是两者差别,然后通过state记录持有锁的数量,等到时候进行释放,为0的时候就是无锁了,把对应状态改为无锁,这里主要就是对AQS的应用,原理层面我们还是去分析下AQS。