Threads Considered Harmful 266
LBR9 writes "James Reinders compares native threads with the goto statement so famously denounced 40 years ago by Edsger Dijkstra. Paraphrasing Dijkstra, he says they both 'make a mess of a program,' and then argues in favor of a higher level of abstraction. A couple of people commenting on the post question whether or not we should be even be treading into the 'swamp of parallelism,' echoing the view recently espoused by Donald Knuth."
No threads? (Score:5, Funny)
Re: (Score:2)
Re: (Score:2)
How about "C++ threads considered harmful"? (Score:5, Insightful)
Re: (Score:3, Informative)
The articles' author explicitly mentions Erlang as a potential solution to threading issues in other languages. In fact he's mainly concerned about POSIX pthreads, Boost threads, Java threads (and presumably Windows low level thread libraries). As I point out in another post below, I disagree with him lumping Java threads in with those used in most C/C++ libraries, as threading support is integrated into the language along with increasingly sophisticated locking support in the library which can be used if t
Re: (Score:2)
I've been working with Cocoa/Objective-C for a while, and I'm starting to develop some of its habits in C++ (immutable strings, smart pointers, Copy-on-Write obj
Re:How about "C++ threads considered harmful"? (Score:4, Funny)
Re: (Score:2)
Re: (Score:3, Interesting)
The problem simply comes in that a program is not obligated to *use* synchronize, or any locking, when it accesses objects. Which means the code is totally unsuitable for integrating into a multithreaded program. And trying to backport thread-safety in is (currently) too difficult, as there are no tools to te
Re: (Score:3, Interesting)
I may have misunderstood (I'm not exactly an expert in threading), but I believe that Erlang handles this is a scarily elegant manner... once assigned, a variable can not be changed.
The = operator in Erlang should be looked at in the mathematical sense, so the following (pseudo) code would fail:
a = 2
a = 1 + 3
Because 1+3 != 2
(Disclaimer: I've briefly dabbled in Erlang, but anyth
Re: (Score:2, Interesting)
Re: (Score:2)
Re: (Score:2)
Except ... (Score:2, Insightful)
Re: (Score:3, Interesting)
Right now, everyone thinks in terms of Turing Machines - we tell the computer what to do. In functional programming, you tell the computer what result you want to achieve (in terms of formulas and such) - and it does it for you.
It's hard to grasp for someone who's used to the Turing way, but it's not for someone who hasn't dealt with it. Programmer should be able to give hints to the CPU (for optimizatio
Re: (Score:2)
Not exactly a new sentiment (Score:5, Informative)
I use threads a fair amount, because they are there. But I kinda wish path expressions [wikipedia.org] would catch on. Let the compiler sort out the scheduling given the constraints - that's the kind of scut work computers are good for anyway.
I'm All For Getting Rid Of Threads, But... (Score:4, Informative)
Re: (Score:3)
Threads only seemed to get really popular with Windows. Unix programming has typically always been multi-process with some form of shared memory. I've heard (and this is unconfirmed hearsay) that CreateProcess() on Windows is so heavyweight that they pushed for a comprehensive threading model instead.
Re: (Score:2)
I later used pthreads, of course, and that was much easier, but multiprocesses always seemed to be "the way things were done" - a
Re: (Score:3, Informative)
Um, if what you've heard is true, why have threads been in Unix for a very long time?
In the early 90s, threads were the "next big thing". Around that time Java was being designed, so it ended up oozing in threadedness. Threads were tacked into Unix as an afterthought somewhere around that era to keep up with the latest fads.
Windows NT was also created in those times. Since threads were seen as the way of the future, the design of Windows NT was heavily focused on threads, and that was touted as making the new OS more "modern". There was not a lot of emphasis on process spawning efficien
Re: (Score:3, Informative)
NtCreateProcess even supports COW fork, by specifying a N
Re: (Score:2)
My major problem with threading is simply that it breaks "encapsulation", if you generalise that term beyond object orientation. Threads have access to everything in the process space, even those objects that you'd rather not have them know about. That's why tuplespaces appeal to me: put those objects that are supposed to be synchronised somewhere special for processes to access, and don't bother worrying about everything else.
Re: (Score:2)
If you want limited sharing you can still make use of thread design by using fork or clone to only share the things you want to.
Re: (Score:2)
There are a lot of places where you want a halfway solution, though. For instance, languages embedded in web servers that normally do automatic memory management (like mod_perl), it's difficult to predict memory usage when COW kicks in for a fork model. At the same time, you want separate processes to maintain encapsulation.
Solutions are to not use garbage collected languages (except we usually have plenty of other reasons to use them), throw on a whole lot of RAM (which can get expensive for a whole clus
Re: (Score:2)
Threads on Linux (using NPTL) are actually a result of clone().
processes (Score:4, Interesting)
Re: (Score:3, Insightful)
Apache 1.x is not multi-threaded.
Re: (Score:2)
In addition, Apache 2.0.x and 2.2.x default to mpm_prefork on *nix.
However, Apache reuses its child processes for more than one page load. In addition, HTTP/1.1 allows you to keep a connection open to request multiple pages from it before closing the connction.
Re: (Score:2)
Re: (Score:2)
He is referring to processes as a language mechanism for encapsulating state and communication. Not as in O/S level encapsulation of state.
Language-based processes are very light-weight. Look at Erlang, any of the Occam spin-offs or any of the other theoretical...
hmm, 1960s? That sounds very early for CCS or CSP. Oh dear, I think you're right, he is talking about forking processes for each unit of concurrency. Shoot him, shoot him now
Re: (Score:2)
There are some gotchas when using Apache threads - read here: http://httpd.apache.org/docs/2.0/developer/thread_safety.html [apache.org]
Re: (Score:3, Insightful)
Web server w/o processes OR threads... (Score:4, Informative)
Re: (Score:2)
Mine does.
Or rather, each hit is handed off to a separate process that handles it, but assuming there are no errors, that process will be reused for a future hit. Thus, we can still cache stuff and skip startup costs most of the time, but still use code that may not be thread safe. I entirely agree with the articles author; third party code that claims to be thread safe often isn't. With process isolation, I don't have to care.
Note that I'm running fairly low volume but extremely processor intensive web
Re: (Score:2)
One thread/process per client is an incredibly inefficient way of managing connections on a server, even on Windows. The only thing in its favour is that you don't have to think about the code that you are writing because the connection context is embedded in the thread context, which is handled for you by the OS.
I don't know about writing servers on UNIX, but I do know that you can write a far more efficient server using Windows'
Re: (Score:2)
The Actor model is the solution (Score:3, Interesting)
With the Actor model, whatever data parallelization is there in a program is automatically exposed.
Re: (Score:3, Interesting)
Threads are one thing that Ada does
I disagree with both this guy AND Dijkstra (Score:5, Interesting)
Use the best tool for the job, regardless of whether your CS professors demonized it or not.
Re: (Score:2)
Re: (Score:2)
I certainly abuse global variables in my code, but I write my code for me to solve my problems. The loss of encapsulation that results isn't so extreme when there's one author, and the gain in flexibility is pretty steep.
However, I do think that avoiding nastiness is important, especially as the size of the group codi
Re: (Score:2)
Re: (Score:3, Interesting)
If you don't think that we should be using hardware advances to make things easier on programmers, then why do you use compilers? Compared to hand-tuned machine code specific to each target processor, the stuff that comes out of a C compiler is slower by a factor of 2 to 10 at least. Other languages even more so.
The fact of the matter is that high level tools are almost always the right choice, and the standard rules of optimization apply:
That's not disagreeing with Dijkstra (Score:4, Insightful)
Unless you seriously think people should use gotos instead of loops and if/else statements, then you don't disagree with Dijkstra.
Re: (Score:2)
Re: (Score:2)
-- Erik Naggum [wikiquote.org]
Single Threading Is Harmful (Score:2)
Re: (Score:2)
If someone is using a global variable, goto, or thread model as a "blunt tool" without concern for elegance, readability and robustness, they have already validated all the dire warnings against using these constructs. I use them only where, after rigorous examination, I have decided I can use them without sacrificing the three aforementioned design goals.
Not really news (Score:5, Insightful)
The author of this "article" (and I use the term loosely) doesn't really present such options. He hand waves a few work-in-progress solutions at the end, compares threads to GOTO statements, then asks the readers to fill in the (rather sizable) blanks.
Long story short, it's a good topic of discussion, but the comparison to Dijkstra's famous paper is just an advertising point. Nothing more, nothing less.
X considered harmful (Score:2)
There has been, at least according to the aforem
If you can't stand the heat (Score:2)
And if don't like the taste of that one (what? Dennis Ritchie & Brian Kernighan not good enough for you!) there are other CSP [swtch.com] languages available (what? Sir Charles Hoare not good enough for you!)
Seriously, this problem has been solved for 30 years.
I wonder how long... (Score:2)
Re: (Score:2)
Don't see any serious problems (Score:2)
Re: (Score:2)
Doing what? I'd hope any OS (SMP or otherwise) doesn't significantly use the CPU itself. For an SMP OS to have something to gain by multicore, it has to come from a parallelizable workload, hence threads. (Unless you have enough runnable processes, but that often isn't so.)
Unless you meant more responsiveness / lower interrupt latency or something like that in an OS, which is fair enough, but not exactly using multicore to its fulles
Hmm (Score:3, Interesting)
The problem is not threads per se, but the way they are generally used in programming languages like C and C++. Although const correctness is understood by some C++ programmers, they appear to be a minority if I judge by the code I regularly review. There is also memory management which is a much bigger issue in threaded C/C++ applications than in applications written in Java. The Java library provides good examples of immutable classes, most prominently the String class, that remove a number of problems often encountered with their mutable cousins like std::string. Unlike std::string, I don't have to remember to make it immutable by constifying it or wrapping it. The presence of immutable classes, and the more adequate coverage given them along with threading in Java textbooks means that I disagree with the articles' author who lumps Java threads in with pthreads as a bad thing. What we need is more coverage of threading issues and how to alleviate them in intermediate level C/C++ textbooks, because despite the fact that threading is not built into those languages or their standard libraries, concurrency has become too important to ignore once you go beyond the basics.
Right. Mod parent up. (Score:3, Interesting)
The problem is not threads per se, but the way they are generally used in programming languages like C and C++
Right. C and C++ provide zero help in dealing with the isolation issues of threading. The languages have no concept of parallelism (there's "volatile", but that's about it.) There were 1980s languages that did offer some help, such as Modula I/II/III, Ada, and Occam. Java has some minimal concurrency support, although it's not well thought out.
There's nothing wrong with multithreaded program
Re: (Score:3, Informative)
If you're familiar with CORBA, and underwhelmed by SOAP, then you might like to check out ICE [zeroc.com]. It's an attempt to do CORBA "better" - in other words, without the designed by committee and everything bar the kitchen sink aspects that ruined CORBA. I was initially a little bit sceptical, but having played around with it for a notifications system I've become really impressed.
Re: (Score:2)
you might like to check out ICE
There are lots of little IPC packages. Too many, actually. OpenRPC is somewhat dated, but OK. The last time I had to do this, I used Python, CPickle and pipes. But that wasn't a IPC-intensive application. When we did a robot vehicle for the DARPA Grand Challenge, there were about 20 processes communicating via QNX MsgSend/MsgReceive, and that worked out well, including dealing with hard real-time constraints, heavy computation on the same CPU as low-level hard real time
Re: (Score:2)
Don't call a method in the other process, send it data instead.
Re: (Score:3, Interesting)
Re: (Score:2)
I've just seen a very nice presentation on how null pointer exceptions can be avoided using annotations in the Java language. The same presentation also showed how to annotate variables to be immutable: changes to the variable would be picked up by the compiler.
That said, with the possible exception of Java arrays, it's pretty easy to make variables immutable (basic types are referenced by value, collec
Making a parrallel with Edsger Dijkstra's article? (Score:2, Insightful)
The second one made an argument, showed alternatives that were at least summarili demonstrated to be better and used reasoning.
The first one just says "Edsger Dijkstra's paper said goto was harmful and he ended up being right, thus if I say threads are harmful, I'm also right. Oh and here are some threading libraries I've found in a quick google search, they might be better."
Slowaris caused threading (Score:2, Troll)
Linux doesn't need threading.
Re:Slowaris caused threading (Score:4, Insightful)
Complete crap. Threads solve a number of programming problems much more elegantly than forked processes and sharing data through some IPC mechanisms. Anecdote time: a stock price system I worked on. The first generation used separate processes for a single writer and a large number of readers, with shared memory for interprocess communication. This was switched to a threaded implementation for the second generation, which was faster, even though it was using the old LinuxThreads implementation, and more easily maintained as the pthreads API is much richer than IPC ones.
Threads work fine (Score:3, Interesting)
I use them routinely on MS platforms. Background threads for write-behind mechanisms, for self-tuning caches, for animation. The sharing between threads is the more-precise problem, not threads itself. If one knows how to examine the context of a thread, one can see all shared pints and code accordingly. This is no different th
Re: (Score:2)
The problem seems to be that some of the more popular languages don't enforce that behaviour. In other words, the programmer has to be (gasp) competent!
Re: (Score:2)
With different processes you have the same problem as between two different VM's, although you may make use of non-networked resources such as pipes and local files.
The big advantage of threads is that they run in the same memory space. If you use managed code within the threads, this means that the threads cannot access the other thread's memo
Especially if you are organic matter... (Score:2)
Threads are not harmful (Score:2)
As a comparison, I learned to program properly on the Amiga, and its OS was natively threaded, and the architecture actually encouraged it(Likewise, unlike so many people who grew up with PC's, I also feel at home with programming for something like the PS3 or similar), and therefore I inherently think about how things can be split
more detailed analysis from two years ago (Score:2, Informative)
Re: (Score:2)
Great read, thanks.
Re: (Score:2)
"Threads" are not the problem. (Score:3, Interesting)
Writing a safe threaded application is not a difficult task, but it is a different task then writing a single-threaded app. And unfortunately CS programs, books, tutorials, etc, still train people in the single-thread mindset and yes the programs they produce end up being buggy.
And I'm not sure these 'high abstraction' languages are really the 'answer'. I have found that often in higher level solutions the results become even less predictable and tracing what is actually happening when becomes either extremely difficult, extremely inefficient, or just back to the single-thread mentality.
I think the OP talking about how one might be next writing a parrell app shows the real flaw here... the author is going from one mentality, entering another without really thinking it through, and then complaining when old methods don't work well. Take a programmer who STARTED in parrell space and you don't run into these problems.
Re: (Score:2)
The problem isn't with threading - it's how developers approach threading.
All shared write structures must have locking! Use global variables sparingly - perhaps only for communicating exit procedures.
And if you can - use a garbage collector. Seriously - if you're not tied to real-time transactions, a GC is the way to go.
Re: (Score:2)
I actually think a good set of 'training wheels' for getting developers thinking about threaded environments is to introduce them to fork with anonymous shared memory. Much easier to encapsulate things but still teaches how think in terms of multiple threads.
Stay Away from Parallelism!! (Score:2)
Almost All Web Servers Are Multi-Threaded (Score:2)
Re: (Score:2)
Snort.
F90 and SIMD (Score:2)
I've already said this about a dozen times on /., but here goes anyway ;)
In 2001 I worked at CERN, writing simulation and analysis software on a dual P3 machine. The language was Fortran 90, and the compiler made use of SIMD (MMX/SSE) on both processors to parallelize matrix algebra.
The parallelism was abstracted away quite nicely, just as the article suggested. There was probably some thread/process creation under the hood to make use of both CPUs, but the calculations were basically SIMD in natur
Parallelism mimicks the physical world (Score:2)
"Considered harmful" considered harmful (Score:2)
But it's never used like that; it's always used by one opinionated loudmouth who is the only one in the world who considers the practice harmful. You want another example? Look at that crock of an essay "Reply-to munging considered harmful"; the only one who considers reply-to munging harmful is the opinionated loudmouth who wrote that essay, yet the title falsely implies that the community
locking is the problem - is (S)TM the answer? (Score:2)
Locks have problems. In order
Shared State Considered Harmful (Score:2)
having the full compliment of arrogance (Score:2)
I suppose our confidence in driving toward parallelism rests on intuition, such as analogizing that the brains of all higher animals are parallel processors therefore some solution to the problems of parallel computation mus
chickens (Score:4, Funny)
A) to To other the side. get the
Fancy programming languages are NOT the solution. (Score:5, Interesting)
I'm tired of reading replies to this article that evangelize some fancy-schmancy high-level solution. I wonder if these advocates have ever tried writing production code in such an environment.
Let me give you a wonderful example of when theory simply doesn't meet reality.
Recently, I wrote a bunch of multi-threaded code for a next-generation asymmetric-multiprocessing game console that shall remain nameless. Its operating system has a wonderful complement of synchronization features. There's the usual mutex lock/unlock, and the usual condition signal/wait, but there are also event queues (queues of generic events that can be passed between threads running on different types of processors), lightweight mutexes/conditions, spinlocks, semaphores, reader/writer locks, and so on and so on. Truly a rich palette from which one can paint a wonderfully synchronized multi-threaded application! I then proceeded to try to rewrite a key section of our code in a very multi-threaded way.
The problem was, the first version of this code added NINETY milliseconds per frame to our main thread. A profile showed that nearly all of the extra time was spent in the operating system's synchronization features.
After much rewriting and much pain, I stopped using all of the operating system's synchronization features, and used processor-level atomic operations instead, and finally, the extra code accounted for only FOUR milliseconds per frame in our main thread (with the rest of the time successfully farmed out to separate threads).
I challenge anyone with a fancy-schmancy automatic concurrency solution to demonstrate that it doesn't have this problem.
Re: (Score:2)
Re: (Score:2)
Re: (Score:2)
There. Fixed that for you.
Re: (Score:2)
Most non-trivial programs also need the context they were written in, to be fully grokked.
Re: (Score:2)
One of the things I look for in interviewing a programer is their perspective on 'goto'... if they claim it should never be used ever for anything by anyone in any situation that is generally a black mark against them.
Re: (Score:3, Interesting)
Re: (Score:2)
It can be really useful for jumping down to a cleanup section of a function where some things need to be manually shut down upon failure of the main function. In these situations there are OOP (or even procedural) ways to also handle it but they tend to require either some rather iffy wrapper classes or complex parameters being passed around. Example:
foo()
{
lib
Re: (Score:2)
but you can imagine how badly that can scale depending on how much can get passed around.
You're using a language that supports goto -- surely it supports pointers?
More relevantly, why wouldn't this work?
I probably wasn't understanding quite what you needed there. I realize some peo
Re: (Score:2)
Re: (Score:2)
Re: (Score:2)
foo () {
// do stuff
// do other stuff
blocking_operation()
}
is nicer to work with than
foo1 () {
// do stuff
// do other stuff
when_done(async_operation(), foo2)
} foo2 () {
}
, espicially if you have lots if local variables used by both "do stuff" and "do other stuff". It doesn't really matter for this use whether the compiler maps the first example to the second example or to OS threads.
Re: (Score:2)
OK, but are you suggesting multiple core processors are, at this point, rare? Yes, threads are only really useful if you have the sort of processor most new computers have.