All!
I found strange code in LinkedBlockingQueue:
private E dequeue() {
// assert takeLock.isHeldByCurrentThread();
Node<E> h = head;
Node<E> first = h.next;
h.next = h; // help GC
head = first;
E x = first.item;
first.item = null;
return x;
}
Who can explain why do we need local variable h? How can it help for GC?
To better understand what happens let's see how the list looks like after executing the code. First consider an initial list:
1 -> 2 -> 3
Then h
points to head
and first
to h.next
:
1 -> 2 -> 3
| |
h first
Then h.next
points to h
and head
points to first
:
1 -> 2 -> 3
| / \
h head first
Now, practically we know that there is only active reference pointing to the first element, which is by itself (h.next = h
), and we also know that the GC collects objects that have no more active references, so when the method ends, the (old) head of the list ca be safely collected by the GC since h
exists only within the scope of the method.
Having said this, it was pointed out, and I agree with this, that even with the classic dequeue method (i.e. just make first
point to head.next
and head
point to first
) there are no more references pointing towards the old head. However, in this scenario, the old head is left dangling in memory and still has its next
field pointing towards first
, whereas in the code you posted, the only thing left is an isolated object pointing to itself. This may be triggering the GC to act faster.