When reading the source code of LinkedBlockingQueue
, I notice that it uses a linked list with ReentrantLock
. But since Java already has an implementation called LinkedList
, why isn't it used in LinkedBlockingQueue
directly? Similarly, linked list is implemented again in LinkedBlockingDeque
.
public class LinkedBlockingDeque<E> extends AbstractQueue<E>
implements BlockingDeque<E>, java.io.Serializable {
private LinkedList<E> queue;
final ReentrantLock lock = new ReentrantLock();
// take the remove(Object) method as example
public boolean remove(Object o) {
if (o == null) return false;
fullyLock();
try {
queue.remove(o);
return false;
} finally {
fullyUnlock();
}
}
// ... the rest of the class
}
What isn't it implemented like the code above? What's the trade-off behind this?
Here are some reasons that a private linked list class is used:
The linked list used in LinkedBlockingQueue
is a singly linked list. LinkedList
is doubly linked. This uses more memory, and has a small performance penalty. (This doesn't apply in the LinkedBlockingDeque
case.)
LinkedList
provides fail-fast iterators, and uses a modCount
field to detect concurrent modification. This must be incremented on each list operation that modifies the list. That is a small performance penalty compared with LinkedBlockingQueue
and LinkedBlockingDeque
which provide weakly consistent iterators, and don't have a modCount
.
LinkedBlockingQueue
and LinkedBlockingDeque
are by design weakly consistent. If they were to use LinkedList
under the hood, the latter's fail-fast behavior could not be hidden ... as @Holger pointed out.