[concurrency-interest] Proposal for Hybrid Threading Model and simpler Async IO
dl at cs.oswego.edu
Fri May 9 08:43:54 EDT 2014
On 05/07/2014 11:54 AM, Joel Richard wrote:
> Quick update: The original thread was resurrected and Jeremy Manson from Google
> wrote that they are implementing something quite similar internally
> (http://mail.openjdk.java.net/pipermail/jdk9-dev/2014-May/000670.html). Before I
> reinvent the wheel, I am trying to find out if is interested to share his
> research and concept. That would help a lot and could even decide whether or not
> this will ever be implemented officially in the JVM.
Sorry for delays in addressing this.
Backing up first: Providing lighter-weight thread-like constructions
has been a focus of attention in concurrency for a few decades.
The main idea of the JDK5 java.util.concurrent.Executor
framework was to decouple the notion of parallel execution
from contextual details that might vary (processes vs threads
vs tasks vs even FPGA or GPGPU strands). This works perfectly
if Executors can enforce their contextual usage constraints,
which they often either cannot do or choose not to do.
Usually, they just tell people to please not use Thread
methods or ThreadLocals, and in some cases like ForkJoin-related
classes tell people to please not block. This doesn't always
work out well because users do not want to change their
Thread-based code to use alternative constructions. And it
is hard to create alternatives for all possible ways to block
threads. (See the nested stream parallelism discussion on
this list for one case in point.)
There are (at least) two ways to try to address this. One is as
you suggest, to swap Thread stacks on blocking operations.
Another is to generate another thread to perform any available
work while the original thread blocks. ForkJoinPool uses
a form of this. It is in general a safer move, because
it preserves the relationship between threads, thread-locals,
and stacks assumed by other user and VM code. Plus it tolerates
cross-VM dependencies in which both a thread and its continuation
must make progress, which can occur when blocking is due to IO
representing message sends across cooperating processes on
different machines, that might otherwise lock up.
However, as we've found, even the "safe" strategy for doing this
is not a cure-all. Whether done via new threads of new stacks,
we have found that it is possible (and not rare) for users to
write code that leads to unchecked resource use -- positive
feedback-like loops in which an unbounded number of threads/stacks
must be created. For ForkJoinPool, the best practical alternative
appears to be to limit to constructing the minimal resources that
FWIW, I'm encouraged that the concurrency support community is
slowly but surely discovering ways of supporting usages that
avoid the underlying problems to begin with. For example,
as Jeremy Manson noted, most programmers tend not to like most
async and non-blocking IO APIs. But most programmers seem to like
the non-IO-oriented (CompletableFuture+lambda), and similar
(and layerable) Promise- Reactive /Rx-, async-actor-based extensions.
So we plan to further improve and integrate these for JDK9.
More information about the Concurrency-interest