公平锁与非公平锁
公平锁与非公平锁即fairSybc和NonfairSync。
简单说一下两个锁的区别:
顾名思义,公平就是先到先得,比如A和B线程均需要获得一个锁,但是此时锁正在被另一个线程C占据着,这是如果A先来B后来。那么当C释放锁以后,A就会获得这个锁。
如果是非公平的话,可能B后来但是能比A先获得锁。
ReentrantLock可以设置锁的属性为公平还是非公平
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
public ReentrantLock() {
sync = new NonfairSync();
}
默认无参构造创建的是非公平锁,这样做的好处就是能够提高性能。至于为什么非公平锁能提高性能,我们等下分析源码解释。
直接上两种锁 获取锁的源码
先公平锁
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); //更新state值
return true;
}
return false;
}
}
c表示当前线程的状态。
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());
}
公平锁获取锁的条件是是否有等待队列,有的话就尝试获取锁。
非公平锁
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()) {
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
release释放锁
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);
}
setState(c);
return free;
}
lock()
public void lock() {
sync.acquire(1);
}
线程每次调用lock方法,如果成功获取的话,state值就会加1。
当一个线程获取到了锁之后state值在每次一获取和释放锁之后会更新,只有当state值为0时,别的线程才有可能获取到这个锁,进而执行自己线程的任务。