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

Martin Buchholz martinrb at google.com
Mon Dec 1 17:41:37 EST 2014


If all you want to do is to have one thread produce a single result
while another waits, that sounds a lot like Future, and both recent
FutureTask and CompletableFuture ought to be more efficient than a
1-element ABQ.

On Mon, Dec 1, 2014 at 2:34 PM, Charles Oliver Nutter
<headius at headius.com> wrote:
> Ahh yes, that's another one I tried. Sadly it was *also* still slower
> than using a single-element ArrayBlockingQueue.
>
> I will try to explore the options again and report back, so I know
> I've got my facts straight.
>
> - Charlie
>
> On Mon, Dec 1, 2014 at 3:02 PM, Vitaly Davidovich <vitalyd at gmail.com> wrote:
>> Have you tried SynchronousQueue for the handoff?
>>
>> On Mon, Dec 1, 2014 at 3:17 PM, Charles Oliver Nutter <headius at headius.com>
>> wrote:
>>>
>>> Sense and sanity prevail! Given the new information that this is
>>> probably my fault, I dug a bit deeper...and found a race within my own
>>> code. The thread interrupt logic in JRuby was firing before an
>>> unblocker function was installed, causing the interrupt to just set
>>> flags and not forcibly interrupt the thread. The blocking call then
>>> proceeded and the flags were not checked again until after it had
>>> completed. Fixed it by adding a second flag check *after* the
>>> unblocker has been set but *before* making the blocking call, and it
>>> seems solid now.
>>>
>>> Incidentally, I have a question...
>>>
>>> This logic is being used to emulate fibers (coroutines) in JRuby. A
>>> fiber belongs to a given thread, and there may be many active fibers
>>> within a thread, but none of them run concurrently. Every transfer
>>> into a fiber is an explicit hand-off. If you're familiar with Python
>>> generators or Go's goroutines, you get the idea. I've struggled to
>>> find the right data structure to efficiently implement this hand-off.
>>>
>>> * Exchanger was just about the slowest way. I never figured out why.
>>> * Manually implementing it with park/unpark worked, but I could never
>>> get it perfect. Might have been this race or another race, so I may
>>> revisit.
>>> * new ArrayBlockingQueue(1) ultimately ended up being the fastest by a
>>> wide margin.
>>>
>>> I believe I've asked this before, but what's the fastest way to
>>> *explicitly* transfer control to another thread in an interruptible
>>> way?
>>>
>>> Thanks for clarifying things :-)
>>>
>>> - Charlie
>>>
>>> On Mon, Dec 1, 2014 at 2:02 PM, Martin Buchholz <martinrb at google.com>
>>> wrote:
>>> > On Mon, Dec 1, 2014 at 11:50 AM, Charles Oliver Nutter
>>> > <headius at headius.com> wrote:
>>> >> I'm working to narrow that down now. You're right...I don't expect to
>>> >> have found a bug, but I'm having trouble explaining the behavior I'm
>>> >> seeing.
>>> >>
>>> >> Just to clarify the key point, though: LockSupport.park should be 100%
>>> >> wakeable using Thread#interrupt, yes? There's no situation where a
>>> >> thread in park would *not* be expected to wake up in response to
>>> >> Thread#interrupt?
>>> >
>>> > Right - park() is allowed to return spuriously, but not allowed to
>>> > spuriously fail to return !
>>> > But these methods are usually called in a loop, and if a caller failed
>>> > to check or notice the interrupt then it would call park again.
>>> _______________________________________________
>>> Concurrency-interest mailing list
>>> Concurrency-interest at cs.oswego.edu
>>> http://cs.oswego.edu/mailman/listinfo/concurrency-interest
>>
>>


More information about the Concurrency-interest mailing list