[concurrency-interest] ArrayBlockingQueue (and possibly others) not waking on interrupt?

Charles Oliver Nutter headius at headius.com
Mon Dec 1 19:45:29 EST 2014

On Mon, Dec 1, 2014 at 5:23 PM, Josh Humphries <jh at squareup.com> wrote:
> A future probably won't do since it's single use, but for this case, control
> needs to keep swapping between consumer and co-routine and back. I wonder if
> a there's a way to get a Phaser to work (plus a volatile field to actually
> store the item being transferred).

Right, future is one-shot and I need this to be a generator.

I tried to think through Phaser but at the time I could not use it
without introducing an additional library dependency.

> I've actually toyed with exactly this sort of thing, emulating
> generators/co-routines in Java using multiple threads. My experiments used a
> SynchronousQueue, and it was painfully slow.

My experience as well. It was better than Exchanger, but not by much.
ABQ was *much* faster.

> BTW, it seems like one issue
> with ArrayBlockingQueue(1) is that it's not a perfect exchange. You can have
> a single element in the queue, unconsumed, instead of a synchronous
> hand-off. I think that means that the generator thread is always one ahead
> of the consumer thread. (Although maybe I'm imagining the rest of your
> implementation incorrectly. And perhaps this fact doesn't strictly matter.)

Every fiber round-trip involves two queues (basically, every
transferrable entity has their own queue). The calling thread triggers
the receiving thread by feeding it the next value via the receiving
thread's queue (Fiber#resume in Ruby). It then waits on its own queue
for a response. This allows one-to-one round trips as well as fiber
"transfers" where a chain of them call each other, eventually ending
up back at the initiator.

I think I'll dig up my park/unpark-based impl and give it another
shot. It works basically like you describe, with a volatile transfer
field and explicit parking/unparking. I agree it will probably be the
fastest option, if I can get it to play nicely with some other Ruby
threading oddities (Thread#kill, Thread#raise... sigh).

- Charlie

More information about the Concurrency-interest mailing list