Summary
In an O'Reilly Radar post, Nat Torkington notes the twin trends of multicore CPUs and interest in alternate languages, which point to a possibly threadless world. He suggests that thread-based concurrency may be replaced with coordination models, such as MapReduce. What do you think the future holds for threads in today's major languages?
Advertisement
A recent blog post by O'Reilly columnist Nat Torkington, Threads Considered Harmful observes the intersection of two trends as they relate to concurrent programming:
The first is a [trend] towards multicore systems and the growing importance of distributed execution... if you want your program to run faster, the days of buying faster hardware are coming to an end. Instead, we're looking at a time when you must make your program run faster on more (slow) hardware. Enter parallel programming, clusters, and their hyped big brother "grid computing..."
The second is the increasing relevance of languages like Erlang, Haskell, and E.
He points out that threads have proven difficult to program on multicore CPUs due to threads' inherently non-deterministic nature. Torkington notes that developers are increasingly open to using alternate languages to solve concurrency problems:
As the need for speed forces us out of our single core procedural comfort zone, we're looking more and more at "niche" programming languages for inspiration. Haskell has quite the following among the alpha geeks we know (e.g., the Pugs project), and OCaml has a small but growing group of devotees. Then there was the huge interest in Smalltalk at Avi Bryant's OSCON talk last year.
Torkington's post also mentions concurrency techniques not based on threads, such as MapReduce, which has implementations in several major languages.
What do you think is the future of threads in the context of today's major programming languages, such as Java?
To be honest, this is just inversion of control at the threading level. It's not really all that different from the transition of people realising that they don't need to subclass Thread, but can provide a Runnable. In the functional/mapreduce world, you just give a calculation and let the runtime decide how best to schedule it.
Note that mapreduce (at least, the google one, to which I believe you are referring) is highly specialised for a particular purpose. That won't fit all models of computation. If you are interested in this kind of work, I recommend investigating Erlang which defines a set of intercommunicating processes that the runtime weaves together.
I wouldn't have said "Threads considered harmful" -- after all, using a thread has been just as (un)safe over the years, and it's not going to creep up on you in the middle of the night. Rather, the question should be "should we be doing programming in a different way in the future". The answer is always yes, regardless of when you ask that question, though. It's just that the focus over the next few years is going to be multi-core, rather than ever faster single processors.
What do you think is the future of threads in the context of today's major programming languages, such as Java?
Imperative languages can't get away from the lock/process/unlock model.
Functional languages are better candidates for taking advantage of multiple core CPUs, but only if the cost of computation delegation becomes insignificant.
> What do you think is the future of threads in the > context of today's major programming languages, such as > Java? > > Imperative languages can't get away from the > lock/process/unlock model. > > Functional languages are better candidates for taking > advantage of multiple core CPUs, but only if the cost of > computation delegation becomes insignificant.
You're right, but I think what we'll see is more of an adoption of functional techniques and possibly some language extensions in imperative languages rather than adoption of pure functional languages.
> > Functional languages are better candidates for taking > > advantage of multiple core CPUs, but only if the cost > of > > computation delegation becomes insignificant. > > You're right, but I think what we'll see is more of an > adoption of functional techniques and possibly some > language extensions in imperative languages rather than > adoption of pure functional languages.
Exactly. The functional approach seems to work on a higher level of abstraction while loops are good at a very detailed level. Not every loop or every part of an application should be multi-threaded.
I already am using functional style designs in Java partly considering the possibility of threading (we are already running on machines with a dozen or so processors) but also because resource management is much easier in a functional approach. It's not that we need functional languages to do these things, it's more of an educational and political problem. New features (like closures in Java) help with the educational part but the political side is getting rid of this idea that there's a functional way and an imperative way and once you pick your side you stick with it. All developers should understand both approaches. I know I was not introduced to functional concepts early enough.
Could you please elaborate on the idea of Funtional Patterns in Java? Sounds interesting - a good way for me to get introduced to FP. Any articles, web sites, etc???
> ...I think what we'll see is more of an > adoption of functional techniques and possibly some > language extensions in imperative languages rather than > adoption of pure functional languages.
I imagine imperative languages will provide an ability to mark and enforce side-effect free routines, somewhat like what C++ does with the "const" keyword. Then the compiler will be able to identify opportunities for safe parallelism.
Just imagine the horrors of trying to build a CRUD database program with a GUI interface in a language that had no concept of mutable state!
> Could you please elaborate on the idea of Funtional > Patterns in Java? Sounds interesting - a good way for me > to get introduced to FP. Any articles, web sites, etc???
I don't know if I can give you a good pointer. The way that OO could be designed to imitate functional approaches really hit me when working with Python.
The basic idea that I am talking about is easy and you've probably used it without realizing it. I think SAXHandler and any other Builder pattern implementation are basically Functional in design.
Take the Iterator pattern implemented in Java over a List:
for (String s : list) {
doSomethingExciting(s);
}
A functional-style equivalent might look like this:
class ForEach<T>(Function<T> f)
{
privatefinal Function<T> f;
public ForEach(Function<T> f)
{
this.f = f;
}
publicvoid exec(Iterable<T> i)
{
for (T t : i) {
f.exec(t);
}
}
}
You still might be saying, "um OK. So what, it's still more typing." But the value is that now, we can define all kinds of exotic ForEach implementations. I often use this for managing resources like DB connections because I can write one finally block for all my queries instead of hoping every developer remembers to close everything the right way in a finally block in hundreds if not thousands of places in the code. In regards to this thread, we can write a ForkEach implementation that forks and joins, executing the iteration in parallel. Since threading can be tricky, it's really valuable top be able to have one implementation of this that can be refined and considered very thoughtfully by a threading expert.
On a side note, if we had function pointers in Java, a lot of the boilerplate code in my example disappears which is why I think it's a worthwhile addition.
> I imagine imperative languages will provide an ability to > mark and enforce side-effect free routines, somewhat like > what C++ does with the "const" keyword. Then the compiler > will be able to identify opportunities for safe > parallelism.
I think that's a good idea but a lot of developers don't understand the concept of a idempotent operation and will struggle to identify them. Again this is an educational issue but would impact upon the usefulness of this feature.
> Just imagine the horrors of trying to build a CRUD > database program with a GUI interface in a language that > had no concept of mutable state!
There are a lot of useful things that are just naturally imperative and other things that are more naturally functional. The hard part is getting both camps to admit this.
>I think that's a good idea but a lot of developers don't >understand the concept of a idempotent operation and will >struggle to identify them. Again this is an educational >issue but would impact upon the usefulness of this feature.
I was taught that you assume that an operation should be idempotent, and then struggle to keep it that way. So you identify functions that are not idempotent.
> I was taught that you assume that an operation should be > idempotent, and then struggle to keep it that way. So you > identify functions that are not idempotent.
I'd wager that the majority of developers don't know what the term idempotent means.
While I was thinking about it, though, I realized that I've seen this recently when writing stored procedures. I had to label them as 'not deterministic'. Maybe it's not as complex as I thought. Compiler support would be helpful too. There's also some interesting stuff happening with escape analysis in Java that can determine if Objects can be allocated on the stack and whether synchronization can be removed etc. I wonder if that or something similar could be used to implement automatic parallelism without manual marking.
> I'd wager that the majority of developers don't know what > the term idempotent means.
While I am "familiar" with it I looked it up to make sure I understood it correctly. It's a big funny word, and I think it is used slightly differently in CS than in math. But the concept certainly is not rocket science.
> While I was thinking about it, though, I realized that > I've seen this recently when writing stored procedures. I > had to label them as 'not deterministic'. Maybe it's not > as complex as I thought. Compiler support would be > helpful too. There's also some interesting stuff > happening with escape analysis in Java that can determine > if Objects can be allocated on the stack and whether > synchronization can be removed etc. I wonder if that or > something similar could be used to implement automatic > parallelism without manual marking.
I think that the developer should indicate that methods are "const" or "idempotent" (different meanings!), and that objects are immutable, and the compiler should check that what the developer is asserting appears to be true. If the compiler assumes whatever annotations the developer makes are correct, then things will blow up. If the compiler tries to figure it out entirely itself, then writing methods that the compiler will recognize and optimize becomes tricky.
Besides, I think such things should be part of the contract defined in the interface.
As a starter, I propose adding a "Immutable" marker type to Java, along with compiler checks to validate immutability.
> I think that the developer should indicate that methods > are "const" or "idempotent" (different meanings!), and > that objects are immutable, and the compiler should check > that what the developer is asserting appears to be true. > If the compiler assumes whatever annotations the > e developer makes are correct, then things will blow up. > If the compiler tries to figure it out entirely itself, > , then writing methods that the compiler will recognize > and optimize becomes tricky.
Const would seem to be fairly simple to check but idempotence would seem a little more difficult to verify.
> Besides, I think such things should be part of the > contract defined in the interface. > > As a starter, I propose adding a "Immutable" marker type > to Java, along with compiler checks to validate > immutability.
I find it interesting that generic declarations that use variance can be used to create a pseudo-const reference to a mutable Object. But like anything else with Java generics it's easily subverted, of course.