views:

68

answers:

3

Reading Java's ConcurrentLinkedQueue Docs, I wonder why it is not possible for the implementation to store the size:

Beware that, unlike in most collections, the size method is NOT a constant-time operation. Because of the asynchronous nature of these queues, determining the current number of elements requires a traversal of the elements.

Where in the source is this "asynchronous nature"? I only see a while-loop to retry enqueing until the AtomicReferences match the expected values/references. Why is it not possible to increment an size:AtomicInteger after successfully offering a value to the Queue?

Thanks alot.

A: 

Why is it not possible to increment an size:AtomicInteger after successfully offering a value to the Queue?

Probably because that offer/decrement could not be done atomically without adversely affecting the concurrency of the method.

Kevin
hotzen
+1  A: 

One of the important performance benefit of ConcurrentLinkedQueue comes from the fact that you don't worry about the tail when you update the head, and vice versa, right?

This means basically that 2 threads can poll/offer at the same time without interfering (if the queue size wasn't 0, that is).

This weren't the case if you had a counter. Even if it was a AtomicInteger which has good concurrency, you will still have increased possibility of having failed CAS operations because now you have this "hot spot" that you update every time you do poll/offer.

Not entirely sure if the authors mean this when they say "asynchronous nature", but I think this is the biggest reason they don't have a counter like you suggested.

Enno Shioji
Makes sense, thank you. But I really wonder what they mean with the "asynchronous nature"...
hotzen
@hotzen: Why not ask the authors? I'm sure they'll give you an answer. Just google "concurrency-interest" and post on their mailing list..
Enno Shioji
+1  A: 

Imagine you have two threads, one adding a new item, and the other deleting an item. There are no items in the queue at the start.

Suppose the first thread adds the item, immediately followed by the other thread removing the item and decrementing the size, at which point your size is at -1, then the first thread increments the size to 0.

A slightly contrived example, but you would need to make the whole operation atomic in order to ensure that no other threads could get access to the size of -1.

Finbarr
OK I understand the order in which the decrements/increments are executed is not deterministic. But it should suffice for an counter to get the approximated queue-size, doesn't it?
hotzen
Finbarr, if the queue is managing its own size, it would surely do so within its (sychronized) add/delete methods, yes? So when would the size ever be -1?
CPerkins
@CPerkins: you should read the source before responding. ConcurrentLinkedQueue is "wait-free". It is thread safe without synchronized methods.
CPerkins
@CPerkins: the Impl is wait-free by using atomic-references and by *not* using synchronized. so you would explicitly have to synchronize on the counter as the increment/decrement is by itself atomically but the whole operation of offer/poll is *not* atomically, so Finbarr should be right.
hotzen
@hotzen +1 for a response almost exactly the same as the one I would have typed.
Finbarr
@hotzen and @Finbarr - you're right, and I should learn to read the source before commenting.
CPerkins