reentrantlock可以实现公平锁和非公平锁
ReentrantLock lock=new ReentrantLock(false);
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
非公平锁中源码如下
final void lock() {
// 如果cas尝试获取锁成功(将state锁状态从0设置为1)
if (compareAndSetState(0, 1))
//设置当前线程为独占锁的线程
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
public final void acquire(int arg) {
//如果获取失败返回false 会继续执行将当前线程链入队尾并挂起
if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();//中断自己
}
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
//获取锁状态
int c = getState();
if (c == 0) {
//如果当前没有线程在使用,直接使用cas尝试获取锁,新的线程可能抢占已经排队的线程的锁的使用权,
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);// 设置当前线程独占锁
return true;
}
}
//如果不为0则判断当前线程是不是独占锁的线程
else if (current == getExclusiveOwnerThread()) {
// 如果是将锁数量状态值+1(可重入锁来源)
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
//请求即没有获取到锁,也不是当前独占锁的线程,返回false
return false;
}
非公平锁主要就是线程来了之后就进行抢占锁的操作,不管队列中是否有排队的线程与否
我整理的流程图如下
公平锁源码
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
// 获取锁状态
int c = getState();
// 如果当前没有线程获取锁,
if (c == 0) {
// !hasQueuedPredecessors()保证线程都按顺序使用锁
// 判断当前线程是否为等待队列中的头结点
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;
}
公平锁中能够保证公平的就是这个方法 hasQueuedPredecessors() 来保证线程都按顺序使用锁
就是来判断当前线程是否处于队列中的头结点,如果不是头结点那么就需要排队,如果是头结点就去尝试获取锁
public final boolean hasQueuedPredecessors() {
// The correctness of this depends on head being initialized
// before tail and on head.next being accurate if the current
// thread is first in queue.
Node t = tail; // Read fields in reverse initialization order
Node h = head;
Node s;
return h != t &&
((s = h.next) == null || s.thread != Thread.currentThread());
}
我整理的流程图如下