[concurrency-interest] Single producer, single consumer: unexpected delays for producer

David Holmes dcholmes at optusnet.com.au
Mon Aug 11 20:29:17 EDT 2008


Dan,

> 3) I put some code in to keep track of how many messages are
> typically in the queue when the consumer thread finishes it's take(),
> and it is typically 0... ie the majority (around 80-90%) of the time
> a single message is being removed from the queue.

Okay so that explains the contention. The producer is expending effort
acquiring two locks and waking up the producer.

> that's still a big difference... specifically:
>
> for (;;) {
> 	CharBuffer chars = CharBuffer.wrap(queue.take());
> 	ByteBuffer bytes = encoder.encode(chars);
> 	socketChannel.write(bytes);
> }
>
> causes queue.offer(message) to take 3 times longer to execute than if
> the consumer executes:
>
> for (;;) {
> 	CharBuffer chars = CharBuffer.wrap(queue.take());
> 	ByteBuffer bytes = encoder.encode(chars);
> }

Can I assume that in the fast case the queue size is not normally zero? If
so my theory here is that when the consumer uses the socketChannel it is
introducing additional contention with the prodcuer that keeps the producer
and conumer effectively in lock-step:
- consumer blocks on take()
- producer gets item and does offer() and has to wakeup consumer
- consumer processes item and uses resources needed by producer
- producer is blocked or delayed getting next item
- consumer calls take() again and blocks
- producer produces and calls offer() and has to wakeup consumer
- repeat

However in that case I would expect:
  for(;;) queue.take();
to also impose maximum contention with the producer.

David



More information about the Concurrency-interest mailing list