ReentrantLock源码
Sync
abstract static class Sync extends AbstractQueuedSynchronizer {private static final long serialVersionUID = -5179523762034025860L;abstract void lock();/***非公平鎖Acquire*/final boolean nonfairTryAcquire(int acquires) {final Thread current = Thread.currentThread();int c = getState();if (c == 0) {//競爭鎖if (compareAndSetState(0, acquires)) {setExclusiveOwnerThread(current);return true;}}//如果本線程已經(jīng)獲得鎖,僅增加state。else if (current == getExclusiveOwnerThread()) {int nextc = c + acquires;if (nextc < 0) // overflowthrow 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() {return getExclusiveOwnerThread() == Thread.currentThread();}final ConditionObject newCondition() {return new ConditionObject();}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}}NonfairSync
static final class NonfairSync extends Sync {private static final long serialVersionUID = 7316153563782823691L;final void lock() {//首先嘗試一下,不成功再acquireif (compareAndSetState(0, 1))setExclusiveOwnerThread(Thread.currentThread());elseacquire(1);}protected final boolean tryAcquire(int acquires) {return nonfairTryAcquire(acquires);}}FairSync
static final class FairSync extends Sync {private static final long serialVersionUID = -3000897897090466540L;final void lock() {acquire(1);}protected final boolean tryAcquire(int acquires) {final Thread current = Thread.currentThread();int c = getState();if (c == 0) {//判斷本線程在隊列中是否有前置節(jié)點(即有優(yōu)先本節(jié)點的)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;}} 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 orderNode h = head;Node s;return h != t &&((s = h.next) == null || s.thread != Thread.currentThread());}ReentrantLock
public void lock() {//根據(jù)公平鎖標志決定call哪個sync.locksync.lock();}public void lockInterruptibly() throws InterruptedException {sync.acquireInterruptibly(1);}public boolean tryLock() {//call非公平方式return sync.nonfairTryAcquire(1);}public boolean tryLock(long timeout, TimeUnit unit)throws InterruptedException {return sync.tryAcquireNanos(1, unit.toNanos(timeout));}public void unlock() {sync.release(1);} protected final boolean tryRelease(int releases) {//減releasesint c = getState() - releases;//如果當前線程不是獨占線程,則拋出異常if (Thread.currentThread() != getExclusiveOwnerThread())throw new IllegalMonitorStateException();boolean free = false;if (c == 0) {//僅當c為0時,才表示一個線程完全釋放了鎖,因為可重入。free = true;setExclusiveOwnerThread(null);}setState(c);return free;}AbstractQueuedSynchronizer參考:AbstractQueuedSynchronizer源碼解析
ConditionObject參考:ConditionObject源碼
公平鎖相比非公平鎖的不同
公平鎖模式下,對鎖的獲取有嚴格的條件限制。在同步隊列有線程等待的情況下,所有線程在獲取鎖前必須先加入同步隊列。隊列中的線程按加入隊列的先后次序獲得鎖。
為什么非公平鎖性能好
非公平鎖對鎖的競爭是搶占式的(隊列中線程除外),線程在進入等待隊列前可以進行兩次嘗試,這大大增加了獲取鎖的機會。這種好處體現(xiàn)在兩個方面:
1.線程不必加入等待隊列就可以獲得鎖,不僅免去了構(gòu)造結(jié)點并加入隊列的繁瑣操作,同時也節(jié)省了線程阻塞喚醒的開銷,線程阻塞和喚醒涉及到線程上下文的切換和操作系統(tǒng)的系統(tǒng)調(diào)用,是非常耗時的。在高并發(fā)情況下,如果線程持有鎖的時間非常短,短到線程入隊阻塞的過程超過線程持有并釋放鎖的時間開銷,那么這種搶占式特性對并發(fā)性能的提升會更加明顯。
2.減少CAS競爭。如果線程必須要加入阻塞隊列才能獲取鎖,那入隊時CAS競爭將變得異常激烈,CAS操作雖然不會導(dǎo)致失敗線程掛起,但不斷失敗重試導(dǎo)致的對CPU的浪費也不能忽視。除此之外,加鎖流程中至少有兩處通過將某些特殊情況提前來減少CAS操作的競爭,增加并發(fā)情況下的性能。一處就是獲取鎖時將非重入的情況提前,如下圖所示
?
?
?
?
總結(jié)
以上是生活随笔為你收集整理的ReentrantLock源码的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: AtomicStampedReferen
- 下一篇: ReentrantReadWriteLo