Effectively final
Brian Goetz
brian.goetz at oracle.com
Sat Jul 30 09:18:07 PDT 2011
Reading between the lines, what Neal and I are both saying is: from
where we are now, adding support for mutable local capture in lambdas is
nowhere near our highest language priority.
On 7/29/2011 4:39 PM, Neal Gafter wrote:
> Asynchronous support can be much more usable when supported more
> directly by the language. But until the language does provide that
> support you are forced to do it in a less expressive way using
> libraries. It is true that mutable locals make that less onerous. And
> I personally prefer that lambdas are usable to organize sequential code
> as well as concurrent code (remember, method bodies are always
> sequential today), which may require mutable locals in a language like
> Java. But on the other hand I believe it is better to provide more
> direct language support for asynchronous rather then doing it through
> libraries, and that reduces asynchronous as a motivation for having
> mutable locals in lambdas.
>
> Cheers,
> Neal
>
> On Friday, July 29, 2011, Tim Fox <timvolpe at gmail.com
> <mailto:timvolpe at gmail.com>> wrote:
> > Brian,
> >
> > Thanks for your reply. Comments below
> >
> > On 29/07/2011 19:08, Brian Goetz wrote:
> >> You are right to have these concerns.
> >>
> >> The canonical example is:
> >>
> >> int fooSum = 0;
> >> list.forEach(#{ x -> sum += x.getFoo() });
> >>
> >> You are correct that there are purely sequential use cases that
> >> benefit from this approach, which are not subject to data races. (On
> >> the other hand, it is nearly impossible to write the above
> >> primitive-using code so that it is not subject to data races in a
> >> parallel environment.) We have explored approaches of capturing this
> >> constraint in the language, so that we could prevent or detect when
> >> such a "thread-confined" lambda is used from the wrong thread. While
> >> these are likely feasible, they add complexity.
> >>
> >> Examples like the above have been around for 50+ years. However, it
> >> is worth noting that they became popular in the context of a
> >> sequential, uni-processor world. Rather than expend energy and
> >> introduce additional complexity to prop up an aging and increasingly
> >> irrelevant programming idiom,
> > I'd have to disagree that this approach is aging, the success of node.js
> > and ruby event machine are good counter-examples. They both use the
> > reactor pattern (i.e. a single event loop which executes everything), so
> > the developer does not have to worry about concurrency concerns. This is
> > a huge win in terms of simplicity for the developer.
> >
> > Frameworks like node and eventmachine scale over cores by spinning up
> > more processes, not threads (since there's only one event loop per
> > process). This is less than ideal when you want to share state between
> > event loops.
> >
> > New frameworks like node.x https://github.com/purplefox/node.x (which is
> > what I am working on) allow multiple event loops per process (typically
> > one event loop per core), and then partition objects so they are "owned"
> > by one of the event loops. The framework will then guarantee that all
> > callbacks on those objects are always executed by the same event loop.
> >
> > What you get out of this is the user can write all their code as single
> > threaded, but the system as a whole scales well over available cores
> > without having to spin up more processes.
> >
> > If the framework can guarantee this code is always executed by the same
> > thread, it seems wrong to force users to use AtomicReferences (or
> > whatever) to co-ordinate results from different callbacks.
> >> we instead are directing our energies towards providing more modern,
> >> parallel-friendly idioms, like:
> >>
> >> int fooSum = list.reduce(0, Reducers.INT_SUM);
> >>
> >> which is more compact, more readable (once you learn what "reduce"
> >> means), less error-prone, and can be parallelized by the library.
> >>
> >> You state that "most languages that support closures do allow capture
> >> of mutable local variables." However, most of them have
> >> {little,no,bad} support for safe concurrency or parallelism. If Java
> >> were a strictly sequential language, the story might be different, but
> >> that isn't the reality -- or desirable.
> >>
> >> We had three basic choices here:
> >> 1. Allow arbitrary mutable capture, and leave it to the user to not
> >> create data races.
> >> 2. Complicate the language further by introducing a notion of
> >> thread-confined lambdas, and allow mutable local capture by
> >> thread-confined lambdas.
> >> 3. Prohibit mutable local capture entirely.
> >>
> >> To do (1) in 2011 would be foolish;
> > I agree that 3) should be the default, since most people won't be using
> > frameworks that guarantee access is always by the same thread. But I
> > think it would be great if 2) was an option for those frameworks (and I
> > think they will be a growing trend) which would benefit from a simpler
> > programming style that it would allow.
> >
> >
> >
More information about the lambda-dev
mailing list