ReentrantLock的基本使用
public void reentrantLock(){
ReentrantLock reentrantLock = new ReentrantLock();
try{
reentrantLock.lock();
System.out.println(count++);
}finally {
reentrantLock.unlock();
}
}
变量
//同步器,继承了AbstractQueuedSynchronizer
private final Sync sync;
构造方法
//默认为非公平锁
public ReentrantLock() {
sync = new NonfairSync();
}
//根据fair判断sync 为公平锁或非公平锁
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
主要方法
上锁
/**
*获得锁。
*如果其他线程没有持有锁,则获取该锁并立即返回,将锁持有计数设置为 1。
*如果当前线程已经持有锁,那么持有计数加一并且该方法立即返回。
*如果锁被另一个线程持有,那么当前线程将被禁用以进行线程调度并处于休眠状
*态,直到获得锁为止,此时锁持有计数设置为 1
*
*调用
* 同步器的lock方法,同步器的方法为抽象方法(abstract void lock();),分别* 在公平锁(FairSync)和非公平锁(NonfairSync)中实现
*/
public void lock() {
sync.lock();
}
获得公平锁
/**
*调用acquire()方法上锁
*acquire()为AbstractQueuedSynchronizer类中的方法,方法中会调用*tryAcquire(arg)上锁,如果上锁失败,调用*acquireQueued(addWaiter(Node.EXCLUSIVE), arg)方法将当前线程放进队列中
*tryAcquire()方法默认给子类实现,所以此处调用的是公平锁(FairSync)中实现
*的方法
**/
final void lock() {
acquire(1);
}
/**
* 尝试公平锁
*/
protected final boolean tryAcquire(int acquires) {
//获取当前线程
final Thread current = Thread.currentThread();
//获取当前的锁状态
int c = getState();
//如果没有上锁,则判断线程队列里有没有等待线程,如果没有等待线程设置锁 状态,设置当前拥有独占访问权限的线程,然后返回true
if (c == 0) {
if (!hasQueuedPredecessors() && //判断等待队列里是否有线程
compareAndSetState(0, acquires)) { //设置锁状态
setExclusiveOwnerThread(current); //设置当前拥有独占访问权限的线程
return true; //获取锁成功
}
}
else if (current == getExclusiveOwnerThread()) { //当前线程是否为exclusiveOwnerThread线程,即当前拥有独占访问权限的线程
int nextc = c + acquires; //线程数量加1
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc); //设置锁状态
return true; //获取锁成功
}
return false;
}
获得非公平锁
/**
*非公平锁尝试获取锁
* 如果没有获取到锁,则执行nonfairTryAcquire()非公平锁的获取方法
* 与公平锁的区别在于不会判断等待队列里面有没有线程
* nonfairTryAcquire()是Sync中实现的方法
*/
static final class NonfairSync extends Sync {
final void lock() {
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
}
/**
*非公平锁的获取
*/
final boolean nonfairTryAcquire(int acquires) {
//获取当前线程
final Thread current = Thread.currentThread();
//获取锁状态
int c = getState();
if (c == 0) { //判断是否有锁
if (compareAndSetState(0, acquires)) { //比较并且设置锁状态
setExclusiveOwnerThread(current); //设置当前拥有独占访问权限的线程
return true; //获取锁成功
}
}
else if (current == getExclusiveOwnerThread()) { //当前线程是否为exclusiveOwnerThread线程,即当前拥有独占访问权限的线程
int nextc = c + acquires; //线程数量加1
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc); //设置锁状态
return true; //获取锁成功
}
return false; //获取锁失败
}
释放锁
/**
*如果当前线程持有锁则递减释放
*/
public void unlock() {
sync.release(1); //调用AbstractQueuedSynchronizer里的方法
}
/**
*此方法先调用tryRelease()释放锁,释放成功后查看是否有待唤醒的线程
*如果存在,唤醒后续线程
* tryRelease()由Sync实现
*/
public final boolean release(int arg) {
if (tryRelease(arg)) { //尝试释放锁
Node h = head; //如果释放锁成功,获取下一个待唤醒的线程
if (h != null && h.waitStatus != 0) //如果存在待唤醒的线程
unparkSuccessor(h); //唤醒线程
return true; //释放成功
}
return false; //失败
}
protected final boolean tryRelease(int releases) {
int c = getState() - releases; //获取锁状态
if (Thread.currentThread() != getExclusiveOwnerThread()) //如果当前线程不是当前拥有独占访问权限的线程,抛出异常
throw new IllegalMonitorStateException();
boolean free = false; //
if (c == 0) { //如果锁全部释放完毕
free = true;
setExclusiveOwnerThread(null); //设置当前拥有独占访问权限的线程为null
}
setState(c); //设置锁状态
return free;
}