AQS理解之四—看看我们写的和 ReentrantLock 的公平不公平锁的区别
生活随笔
收集整理的這篇文章主要介紹了
AQS理解之四—看看我们写的和 ReentrantLock 的公平不公平锁的区别
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
AQS理解之四,看看我們寫的和 ReentrantLock 的公平不公平鎖的區別
首先看下ReentrantLock的lock和unlock方法。
不公平鎖版本lock方法
final void lock() {if (compareAndSetState(0, 1))setExclusiveOwnerThread(Thread.currentThread());elseacquire(1); }public final void acquire(int arg) {if (!tryAcquire(arg) &&acquireQueued(addWaiter(Node.EXCLUSIVE), arg))selfInterrupt(); }final boolean acquireQueued(final Node node, int arg) {boolean failed = true;try {boolean interrupted = false;for (;;) {final Node p = node.predecessor();if (p == head && tryAcquire(arg)) {setHead(node);p.next = null; // help GCfailed = false;return interrupted;}//如果2次之后不能獲取到鎖,將自己的線程park,等待unlock時的unpark。if (shouldParkAfterFailedAcquire(p, node) &&parkAndCheckInterrupt())interrupted = true;}} finally {if (failed)cancelAcquire(node);} }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()) {int nextc = c + acquires;if (nextc < 0) // overflowthrow new Error("Maximum lock count exceeded");setState(nextc);return true;}return false;}不公平鎖版本/公平版本unLock方法
public final boolean release(int arg) {if (tryRelease(arg)) {Node h = head;if (h != null && h.waitStatus != 0)unparkSuccessor(h);return true;}return false; }private void unparkSuccessor(Node node) {/** If status is negative (i.e., possibly needing signal) try* to clear in anticipation of signalling. It is OK if this* fails or if status is changed by waiting thread.*/int ws = node.waitStatus;if (ws < 0)compareAndSetWaitStatus(node, ws, 0);/** Thread to unpark is held in successor, which is normally* just the next node. But if cancelled or apparently null,* traverse backwards from tail to find the actual* non-cancelled successor.*/Node s = node.next;if (s == null || s.waitStatus > 0) {s = null;for (Node t = tail; t != null && t != node; t = t.prev)if (t.waitStatus <= 0)s = t;}if (s != null)LockSupport.unpark(s.thread); }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方法:
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; } //其實是判斷了當前head的next節點是否是當前線程,如果是當前線程才可以在state為0時拿到鎖。否則繼續阻塞。 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基本相同,使用了state來代表是否有鎖,0為無鎖,1以上是重入鎖的進入的次數。用一個exclusizeOwnerThread來代表當前持有鎖的線程。自旋來實現阻塞等待,用鏈表來代表阻塞的線程的集合,鏈表上有用的第一個節點即持有公平鎖要解鎖的線程。不用的是我們不能使用Unsafe類,使用的是原子類變量,而這里ReentrantLock中使用了Unsafe類來操作。
總結
以上是生活随笔為你收集整理的AQS理解之四—看看我们写的和 ReentrantLock 的公平不公平锁的区别的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: AQS理解之三,由刚才写的锁转变成一个公
- 下一篇: AQS理解之五—并发编程中AQS的理解