[concurrency-interest] Are functional languages so much better at concurrency?

Osvaldo Pinali Doederlein osvaldo at visionnaire.com.br
Fri Feb 9 07:26:17 EST 2007


Brian Goetz escreveu:
>> Joel, from joelonsoftware, claimed twice that functional languages are 
>> excellent for developing concurrent apps.
>>     
> The side-effect-free property is indeed nice and makes a lot of 
> concurrency problems just go away.  Programming in this style (heavy use 
> of immutable objects, sharing as little state as possible) in stateful 
> languages like Java also makes concurrency easier.
>
> So, the question is, are functional languages better or worse for 
> ordinary programming?  My innate confidence in the efficient market 
> hypothesis tells me there's a reason that languages like C and C++ and 
> Java and Perl and Python have been so successful; they are well-suited 
> to the problems most programmers need to solve and map well to how most 
> programmers think.  Functional languages, despite their obvious 
> mathematical advantages, don't seem to have caught on in mainstream 
> programming.
> _______________________________________________
>   
Yes, I think the trick (like in many other cases) is combining the 
advantages of both models. Haskell is already a great innovation with 
its Modans system, which accomodates things that actually require 
side-effects like I/O in a ghetto that doesn't spoil the rest of the 
language. But they still try to be purely functional for all normal 
computation needs.

In Java, I try to keep code close to functional when possible. See 
http://www.netbeans.org/download/magazine/01/nb01_writing_quality.pdf, 
page 40, "/The final modifier and refactoring: towards functional-style 
Java/". Even inside a single method I try to avoid gratuitous side 
effects - a mutable for loop counter is fine, but updating a local 
variable in a  on-loop code path just doesn't make sense for me, just 
create a new variable and your code is even more readable (see article). 
Updating attributes of "worker" objects - things used temporarily (and 
locally) to perform some task that demand more state than it's 
comfortable to pass around by parameters through several methods - is 
okay too, just don't share the objects. But for shared data that gets 
held by static variables and accessible (even potentially) for multiple 
threads, I try to use only immutable objects. This requires some extra 
work and patience - like when a coworker complains "where are the 
f****** setters in your POJOs, I wanna update'em in the GUI!". But they 
payoff is great, I can build complex, highly scalable server apps where 
you can hardly find a synchronized keyword or a concurrency bug. 
Scalability is great and easy, double the CPUs and the throughput 
doubles, of course if there are no other issues like concurrent, 
pessimist database updates.

Interestingly, I think that the Java EE programming model helps here. 
Your are admonished to not use threads and synchronization, and while 
you can still do that with care, the whole framework is geared towards 
share-nothing code and transactions. Now, transactions are great for 
expensive JTA resources like database and JMS connections, but we still 
don't have STM with or without JTA support, so the EE model doesn't work 
for lean-and-mean shared stuff, such as configuration data, singleton 
instances, caches of fixed domain tables (those critical enough so that 
the overhead of an ORM tool is too big, even with L2 caching), "worker" 
objects that are more expensive to build than to execute, etc. Well, 
just make all that stuff immutable and your're ready to go: scalable, 
efficient AND Java EE-compatible, no locking required.

Great example if Java API design: java.util.regex. My app has a little 
expression language used in decision trees, so I can just bring the 
whole trees to memory and precompile the expressions; any regular 
expressions are Pattern.compile()'d, everything is put in a shared cache 
(beautiful name for static variables), and because all objects are 
immutable including the compiled Patterns, I can use them from multiple 
transactions/threads without synchronization. It's easy, fast, and 
bulletproof.

Bad example of API design: java.text. I cannot use the same trick for 
SimpleDateFormat and the likes, because these objects are neither 
immutable, nor thread-safe. I'm forced to create new formatter objects 
every time, and recreating these objects is expensive (I measured it) 
even though they seem to make some effort to reuse the precompiled state 
from an internal cache (if your're making all that effort, why not just 
working harder on the precompiled state so it can be immutable?). Add 
this to the parse() methods that only accept a String (Pattern at least, 
accepts CharSequence; ideally, both should accept readers/writers or 
streams) and these classes are totally useless for performance-critical 
code... So I end up writing my own date and number parsing/formatting 
methods for often-used formats.

A+
Osvaldo

-- 
-----------------------------------------------------------------------
Osvaldo Pinali Doederlein                   Visionnaire Informática S/A
osvaldo at visionnaire.com.br                http://www.visionnaire.com.br
Arquiteto de Tecnologia                          +55 (41) 337-1000 #223

-------------- next part --------------
An HTML attachment was scrubbed...
URL: /pipermail/attachments/20070209/0a15f878/attachment.html 


More information about the Concurrency-interest mailing list