On 07/30/2015 01:44 PM, David Holmes wrote:
r.isEnqueued() && q.poll() == null && r.isEnqueued() ==> true
What is surprising in the above expression evaluating to true is the
fact that 'r' appears to be enqueued before and after the q.poll()
returns null. I can easily imagine code that would fail because it never
imagined above expression to evaluate to true. For example:
So r has been enqueued and one poll() removes it, so the second poll()
returns NULL, but r still claims to be enqueued. Sorry I'm not seeing
how that is possible.
David
'r' has been enqueued.
Thread-1:
r.isEnqueued() &&
q.poll() == null &&
r.isEnqueued()
Thread-2:
q.poll();
Sequence of actions:
T1: r.isEnqueued() ==> true
T2: q.poll() executed to the following point (see HERE) and 'r' was the
last element in the queue ('head' has been assigned to null):
public Reference<? extends T> poll() {
if (head == null)
return null;
synchronized (lock) {
return reallyPoll();
}
}
private Reference<? extends T> reallyPoll() { /* Must hold
lock */
Reference<? extends T> r = head;
if (r != null) {
head = (r.next == r) ?
null :
r.next; // Unchecked due to the next field having a raw
type in Reference
// >> HERE <<<
r.queue = NULL;
r.next = r;
queueLength--;
if (r instanceof FinalReference) {
sun.misc.VM.addFinalRefCount(-1);
}
return r;
}
return null;
}
T1: q.poll() finds head == null and returns null;
T1: r.isEnqueued() ==> true since r.queue is still ENQUEUED
Regards, Peter