日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

AQS理解之四—看看我们写的和 ReentrantLock 的公平不公平锁的区别

發布時間:2024/9/30 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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 的公平不公平锁的区别的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。