Search code examples
javagarbage-collectionpuzzlejava.util.concurrent

Strange code in java.util.concurrent.LinkedBlockingQueue


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?


Solution

  • 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.