I am not the author, however, I agree fully with him, and I actually do know something about multithreaded programming.
The pitfalls of multi-threaded programming are well understood both in theory and in practice. Using semaphores and locks to secure critical sections is a simple and elegant solution.
Yes, the pitfalls are well understood. However, how to avoid them is not. That's why threads should be avoided as much as possible.
The only danger is abuse from amateur programmers.
That can be said of any programming construct. But of course, what is an amateur programmer? Is it someone not paid professionally? Is it someone who knows less than me about [insert favourite subject here]? Is it someone who is not Edsger Dijkstra? The only way to be really shure you avoid bugs in multithreaded programs is through formal verification, and last time I checked, that was not a topic most "professional" programmers knew very well.
Furthermore, there are many situations where a mutli-threaded program is the best solution.
No, not really many. There are however a few, where multithreaded programming really is needed. But very rarely does those tasks show up in the average programmers task-list.
There are some exceptions to this rule. The win32 api, and java gui programming pretty much forces you to use threads. That doesn't mean they are the best solution, only that your vendor forces you in this direction.
When it comes to data- or processor-intencive tasks, threads are often not the wonderful solution people think it is (think processes, shared memory). The main reason is that you can't test threads separately, and be somewhat sure that when put together they will actually work. With processes, on the other hand, you do have that nice cosy feeling. And, if you for some strange reason find out you need threads anyway, it's much easier to convert two separate programs into one, than it is to convert a hodgepodge of threads and locks into separate processes.
"Multiple processes" is the exact same thing as threads except now you are burdened with using semaphores or pipes to communicate, in the linux kernel there is no entity that corresponds to a thread, all threads are processes.
Forgive me for laughing, but you claim that those programmers who cannot deal with threads properly are amateur programmers, but somehow you find semaphores or pipes to difficult to handle? Using pipes, semaphores, or shared memory is no different than using the multithreaded equivalents of worker-consumer-buffers, locks, or plain memory access. On the other hand, in the latter case, you loose debugability.
What is the difference between calling a function which retrieves data from another process and calling a lock function?
Debugability. Independent testing. Thread-safety.
Co-operative multitasking is and always will be a disaster for anything but simple or embedded applications.
Maybe, but most things are simple, and shouldn't have to deal with the complexities of threads. But in most cases I would prefer an explicit state-machine (as in event-driven programming), or separate processes, to cooperative threads, but that could just as well be because my programming environment make that easier.
Event based programs are the best solution you mention, but simply loony for most applications, they force you to structure your program in a cumbersome way. Event models are useful in programs that must deal with a variety of disparate tasks in real time (videogames, toolkits, word processors, communications systems), you'll notice they aren't widely used outside of this.
I agree that event-driven programs are often unvieldy, especially when they become large. And if you can separate the logic to do some separate task outside the event-loop, that is often better. But then it can just as well be done with processes as with threads.
By the way, network programming is a very good match for event-driven programming.
Your conclusion is faulty as well. It is true that threaded programming requires more care and more forethought, but this is engineering my friend, problems are not guaranteed to be easy to solve, fun, or to be described by any other positive adjective.
Agreed. Sometimes you have to put in the extra work to make a proper solution and design. While it seems easy enough to hack up a few extra threads, this is no excuse for not having a proper architecture and design. And while it is possible to do so using threads, usually processes are easier.
Billions of threaded programs are running on computers everywhere as we speak, proof enough that the concept works and it works fine.
Yes, and billions of programs using mostly goto was running on computers everywhere as Dijkstra wrote his paper. Proof enough that the goto concept works and it works fine. This proves nothing. If you want to "prove" that threads are the better solution, you have to take into account the whole lifecycle of the program. That includes not only initial design and coding, but also the maintenance programming that will go on for maybe decades afterwards. And in that case, it is better to have something that is carefully crafted to be easy to understand, where parts are easily replaceable, and can be debugged and understood separately, than a carefully crafted multithreaded program that needs to be understood as a whole, before you can apply changes to it.
Even worse then that, this is a simple problem with an elegant and simple solution;
On the contrary, multithreaded programming is a complex problem that continue to baffle computer scientists with its complexity. And while there exist some "simple solutions", such as monitors, they are not something you are likely to find in your favourite systems programming language (neither do they solve all problems). By claiming that multithreaded programming is easy, it is you who come out as the uninformed amateur programmer.
which leads me to believe you are either uniformed.
Or simply right.
[ Parent ]