[英]Reduce thread competition by using notify in place of notifyAll
I saw this self implemented bounded blocking queue
.我看到了这个自我实现的有界blocking queue
。
A change was made to it, aiming to eleminate competition by replacing notifyAll
with notify
.对其进行了更改,旨在通过将notifyAll
替换为notify
来消除竞争。
But I don't quite get what's the point of the 2 extra variables added: waitOfferCount
and waitPollCount
.但我不太明白添加的 2 个额外变量有什么意义: waitOfferCount
和waitPollCount
。
Their initial values are both 0.它们的初始值都是 0。
Diff after and before they're added is below:添加前后的差异如下:
Offer
: Offer
:
My understanding is that the 2 variables purpose is that you won't do useless notify
calls when there's nothing wait
on the object.我的理解是,2 个变量的目的是当对象没有任何wait
时,您不会进行无用的notify
调用。 But what harm would it do if not done this way?但是如果不这样做会有什么危害呢?
Another thought is that they may have something to do with the switch from notifyAll
to notify
, but again I think we can safely use notify
even without them?另一个想法是它们可能与从notifyAll
到notify
的切换有关,但我再次认为即使没有它们我们也可以安全地使用notify
?
Full code below:完整代码如下:
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;
}
}
You would need to ask the authors of that change what they thought they were achieving with that change.您需要询问该更改的作者,他们认为他们通过该更改实现了什么。
My take is as follows:我的看法如下:
Changing from notifyAll()
to notify()
is a good thing.从notifyAll()
更改为notify()
是一件好事。 If there are N
threads waiting on a queue's offerLock
or pollLock
, then this avoids N - 1
unnecessary wakeups.如果有N
线程在等待队列的offerLock
或pollLock
,那么这将避免N - 1
不必要的唤醒。
It seems that the counters are being used avoid calling notify()
when there is nothing waiting to ne notified.似乎正在使用计数器避免在没有任何等待notify()
时调用notify()
。 This looks to me like a doubtful optimization.这在我看来像是一个可疑的优化。 AFAIK a notify
on a mutex when nothing is waiting is very cheap. AFAIK 在没有任何东西等待时在互斥锁上发出notify
非常便宜。 So this may make a small difference ... but it is unlikely to be significant.所以这可能会产生很小的差异……但它不太可能是显着的。
If you really want to know, write some benchmarks.如果您真的想知道,请编写一些基准测试。 Write 4 versions of this class with no optimization, the notify optimization, the counter optimization and both of them.编写这个类的 4 个版本,没有优化,通知优化,计数器优化和它们。 Then compare the results ... for different levels of queue contention.然后比较结果......对于不同级别的队列争用。
I'm not sure what "fairness" is supposed to mean here, but I can't see anything in this class to guarantee that threads that are waiting in offer
or poll
get treated fairly.我不确定这里的“公平”是什么意思,但我在这个类中看不到任何东西来保证等待offer
或poll
线程得到公平对待。
Another thought is that they may have something to do with the switch from notifyAll to notify, but again I think we can safely use notify even without them?另一个想法是它们可能与从 notifyAll 到 notify 的切换有关,但我再次认为即使没有它们我们也可以安全地使用 notify ?
Yes, since two locks ( pollLock
and offerLock
) are used, it is no problem to change notyfiAll
to notify
without these two variables.是的,因为使用了两个锁( pollLock
和offerLock
),所以如果没有这两个变量,将notyfiAll
改为notify
是没有问题的。 But if you are using a lock, you must use notifyAll
.但如果您使用锁,则必须使用notifyAll
。
My understanding is that the 2 variables purpose is that you won't do useless notify calls when there's nothing wait on the object.我的理解是,2 个变量的目的是当对象没有任何等待时,您不会进行无用的通知调用。 But what harm would it do if not done this way?但是如果不这样做会有什么危害呢?
Yes, these two variables are to avoid useless notify
calls.是的,这两个变量是为了避免无用的notify
调用。 These two variables also bring in additional operations.这两个变量也带来了额外的操作。 I think benchmarking may be needed to determine performance in different scenarios.我认为可能需要进行基准测试来确定不同场景下的性能。
Besides,除了,
1.As a blocking queue, it should implement the interface BlockingQueue
, and both poll
and offer
methods shoule be non-blocking
. 1.作为阻塞队列,它应该实现接口BlockingQueue
,并且poll
和offer
方法都应该是non-blocking
。 It should use take
and add
.它应该使用take
和add
。
2.This is not a Fairness
queue. 2.这不是Fairness
队列。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.