capturing (or not) mutable local variables
Jesse Sightler
jesse.sightler at gmail.com
Mon Nov 22 16:28:33 PST 2010
FWIW, I agree 100%. The thing that strikes me is that almost all of the
arguments for required final would have applied equally well to required
synchronization on list structures (aka Vectors) just a few years ago.
Ie, some stuff is multithreaded and we want users to be safe without
thinking. But that just doesn't hold up to real scrutiny IMO.
On Nov 22, 2010 6:37 PM, "Vincent Sevel" <vincent at sevel.eu> wrote:
> Hi Brian,
>
>> Safety mechanisms do not need to be perfect to be useful. Your arguments
seem to center around "I can climb the fence, so there's no point in having
it." This argument is, to be blunt, silly. The design principles of the Java
language stress safety, even if there are cases where such safety guards can
be "casted away" by a sufficiently motivated user.
>
> here were the main ideas: the final requirement on variables
> - protects only a very limited number of use cases
> - gives a false sense of protection for all the other use cases that
> do require protection
> - is useless and counterproductive in a large number of legitimate
> use cases, where ugly workarounds have to be used (eg: the final array
> wrapper)
> additionally: the real issue
> - is not with the variable being final or not,
> - but with the closure not respecting the api contract in terms of
> multithreaded safety
>
> With all the messages going back and forth, it strikes me how much
> energy is put in defending the final variable, compared to the forest
> of all the other use cases, such as:
>
> final List square = new ArrayList();
> list.forEach(#{ e -> square.add(e*e); });
>
> How is that really different from your simple broken example? Why
> would we be ok with that one, but not with yours? Should not we be all
> equally screaming 'please do not make this non thread safe closure
> passable to this multithreaded method'?.
>
>> People will do this, they will do this without thinking, and their code
will be broken. It is very hard, even for experts, to get this right.
>
> You realize, of course, that this exact sentence applies to the example
above.
>
>>> public void forEach(@Multithreaded Foreachable block) {...}
>> We explored these issues in the JSR-166 expert group several years ago.
The basic problem is that we don't have a way of reliably expressing
"reference to thread-safe object" in the type system (either statically or
dynamically), so these things revert to being documentation rather than type
assertions.
>
> It is documentation that tools (like compilers) can take advantage of,
> so it is already much better than javadoc, and still way better than
> naming convention.
>
>>> for that matter, you should probably name your loop method forEachMT.
>> Under consideration. Though my intuition is that (a) such a convention
will be hard to stick to and (b) in five years it will probably look silly.
>
> There are predecessors: SwingUtilities.invokeLater/invokeAndWait. Does
> it look silly? May be, but at least, while missing a mean to express
> thread specific constraints on a contract, we can recognize that it
> has some greater visibility than if it was hiding in the javadoc,
>
>
> I see the final requirement on variables as bureaucracy: adds little
> value, and mostly gets in the way of code agility. It is just a lost
> opportunity, but java developers have come to cope with it. However, I
> have battled enough with the double-checked locking anti-pattern, and
> unproperly synchronized code to know that whenever you provide an API
> that does something with threading, it needs to come with a red flag.
> Fix that, and you will realize that the mutable variable is not that
> of a problem.
>
> But may be a reality check might be helpful: send me the forEach
> documentation and signature, and I will ask the 25 developers in my
> company to tell me what is the outcome of the square example.
>
> Thanks for listening. Cheers,
> Vincent
>
More information about the lambda-dev
mailing list