我看到了這個自我實作的 bounded blocking queue。
更改了它提出,旨在通過更換到eleminate競爭notifyAll與notify。
但我不太明白添加 2 個額外變數的意義是什么:waitOfferCount和waitPollCount.
它們的初始值都是 0。
添加前后的差異如下
Offer:

Poll:

我的理解是 2 個變數的目的是notify當wait物件上沒有任何東西時你不會做無用的呼叫。但是如果不這樣做會有什么危害呢?
另一個想法是它們可能與從notifyAllto的切換有關notify,但我再次認為notify即使沒有它們我們也可以安全使用?
完整代碼如下:
class FairnessBoundedBlockingQueue implements Queue {
protected final int capacity;
protected Node head;
protected Node tail;
// guard: canPollCount, head
protected final Object pollLock = new Object();
protected int canPollCount;
protected int waitPollCount;
// guard: canOfferCount, tail
protected final Object offerLock = new Object();
protected int canOfferCount;
protected int waitOfferCount;
public FairnessBoundedBlockingQueue(int capacity) {
this.capacity = capacity;
this.canPollCount = 0;
this.canOfferCount = capacity;
this.waitPollCount = 0;
this.waitOfferCount = 0;
this.head = new Node(null);
this.tail = head;
}
public boolean offer(Object obj) throws InterruptedException {
synchronized (offerLock) {
while (canOfferCount <= 0) {
waitOfferCount ;
offerLock.wait();
waitOfferCount--;
}
Node node = new Node(obj);
tail.next = node;
tail = node;
canOfferCount--;
}
synchronized (pollLock) {
canPollCount;
if (waitPollCount > 0) {
pollLock.notify();
}
}
return true;
}
public Object poll() throws InterruptedException {
Object result;
synchronized (pollLock) {
while (canPollCount <= 0) {
waitPollCount ;
pollLock.wait();
waitPollCount--;
}
result = head.next.value;
head.next.value = null;
head = head.next;
canPollCount--;
}
synchronized (offerLock) {
canOfferCount ;
if (waitOfferCount > 0) {
offerLock.notify();
}
}
return result;
}
}
uj5u.com熱心網友回復:
您需要詢問該更改的作者,他們認為他們通過該更改實作了什么。
我的看法如下:
從改變
notifyAll()到notify()是一件好事。如果有N執行緒在等待佇列的offerLockorpollLock,那么這可以避免N - 1不必要的喚醒。似乎正在使用計數器避免
notify()在沒有執行緒等待時呼叫。這在我看來像是一個可疑的優化。AFAIK anotify在沒有等待的情況下使用互斥鎖非常便宜。所以這可能會產生很小的差異……但它不太可能是顯著的。如果您真的想知道,請撰寫一些基準測驗。撰寫這個類的 4 個版本,沒有優化,通知優化,計數器優化和它們。然后比較結果......對于不同級別的佇列爭用。
我不確定這里的“公平”是什么意思,但我在這個類中看不到任何東西來保證等待offer或poll得到公平對待的執行緒。
uj5u.com熱心網友回復:
另一個想法是它們可能與從 notifyAll 到 notify 的切換有關,但我再次認為即使沒有它們我們也可以安全地使用 notify ?
是的,因為兩個鎖(pollLock 和offerLock)的使用,這是沒有問題的變化notyfiAll,以notify沒有這兩個變數。但是,如果您使用的是鎖,則必須使用notifyAll.
我的理解是,2 個變數的目的是當物件沒有任何等待時,您不會進行無用的通知呼叫。但是如果不這樣做會有什么危害呢?
是的,這兩個變數是為了避免無用的notify呼叫。這兩個變數也帶來了額外的操作。我認為可能需要進行基準測驗來確定不同場景下的性能。
除了,
1.作為一個阻塞佇列,它應該實作介面BlockingQueue,并且兩個poll和offer方法都應該是non-blocking。它應該使用take和put。
2.這不是Fairness佇列。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/354209.html
