該文只是作為個人對于占小狼關(guān)于深入淺出java同步器AQS文的自己一些補充,建議先看他的文章之后再來看該文。有理解不對的地方望提出來共同學(xué)習(xí)。
AQS實現(xiàn)原理是通過子類重寫tryAcquire和tryRelease方法通過CAS指令修改狀態(tài)變量state。(接下來我們會將AbstractQueuedSynchronizer簡寫成AQS方便書寫)
public final void acquire(int arg) {
if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
而我這里想解釋下RreentrantLock內(nèi)部對于tryAcquire()以及tryRelease()的一些自己理解。
對于RreentrantLock主要內(nèi)部是通過構(gòu)造的時候,判斷內(nèi)部使用公平鎖還是非公平鎖從而導(dǎo)致使用的時候有一些差異。
public ReentrantLock() {
sync = new NonfairSync();
}
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
這里公平鎖FairSync和NonfairSync都是繼承自Sync,我們先看下Sync。
abstract static class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = -5179523762034025860L;
/**
* Performs {@link Lock#lock}. The main reason for subclassing
* is to allow fast path for nonfair version.
*/
//lock是由我們的子類來實現(xiàn)
abstract void lock();
/**
* Performs non-fair tryLock. tryAcquire is implemented in
* subclasses, but both need nonfair try for trylock method.
*/
//他默認實現(xiàn)了非公平鎖的Acquire, 通過isLocked方法我們可以知道,state為0的時候為未上鎖狀態(tài),而非0則為上鎖狀態(tài)
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
//如果沒有上鎖,直接通過CAS修改state,如果修改成功,則說明請求鎖成功,將exclusiveOwnerThread設(shè)置為當前線程,這個屬性實際是AQS父類AbstractOwnableSynchronizer內(nèi)的屬性,實際就是為了記錄當前線程
if (c == 0) {
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
//這里如果已經(jīng)上鎖了,則判斷當前上鎖的線程是否為當前線程,是的話繼續(xù)操作,否則直接返回false
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;
}
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;
}
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
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
}
}
接下來看下非公平鎖:
static final class NonfairSync extends Sync {
private static final long serialVersionUID = 7316153563782823691L;
/**
* Performs lock. Try immediate barge, backing up to normal
* acquire on failure.
*/
//非公平鎖會直接去設(shè)置state,如果當前state=0則直接相當于獲得鎖,否則就調(diào)用了AQS的acquire(1)
//我理解非公平鎖不公平的原因在于比如現(xiàn)在AQS的等待隊列有兩個在等待獲得鎖的線程,當前獲得鎖的線程釋放了鎖,而這時候我們使用NonfairSync調(diào)用lock
//的時候,不需要看等待隊列是否有等待獲得鎖的線程,而是直接和等待隊列的下一個獲得鎖的線程競爭鎖,如果競爭成功了,從而直接獲得了該鎖,導(dǎo)致
//等待隊列中應(yīng)該獲得鎖的線程繼續(xù)等待,從而導(dǎo)致了不公平性。
final void lock() {
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
}
接下來再看下公平鎖:
static final class FairSync extends Sync {
private static final long serialVersionUID = -3000897897090466540L;
//根據(jù)上面的分析,這里直接調(diào)用AQS的acquire,如果沒有獲得鎖則直接加入到AQS的等待鎖的線程隊列,從而下次有鎖釋放直接從隊列第一位獲得鎖,保證了公平性
final void lock() {
acquire(1);
}
/**
* Fair version of tryAcquire. Don't grant access unless
* recursive call or no waiters or is first.
*/
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;
}
}
AQS的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.
//尾節(jié)點
Node t = tail; // Read fields in reverse initialization order
//頭節(jié)點
Node h = head;
Node s;
//如果尾節(jié)點==頭節(jié)點的時候,這個時候我們認為等待隊列沒有在等待的線程
//如果頭節(jié)點!=尾節(jié)點但是頭節(jié)點head.next == null,那么這種情況可能是這個時候正好被鎖的線程釋放鎖,并且等待隊列只有一個等待,直接變?yōu)榱薶ead從而head.next變?yōu)榭?,所以說明肯定是有前一個要獲得鎖或者等待鎖的節(jié)點
return h != t &&
((s = h.next) == null || s.thread != Thread.currentThread());
}