As mentioned in other comments, Ousterhout is the inventor of Tcl/Tk (among other things). At around the time this was published, Tcl was my favorite "play with" language, and it naturally lacked sort of built-in threads abstraction. Also at the same time, Tcl/Tk had just become a project at Sunlabs. One of their early projects was to take the event-loop that was the underpinning of Tk and add it to Tcl. I started a…
Why Threads Are a Bad Idea (1995) [pdf]
91–100 of 103 posts
Re: Why Threads Are a Bad Idea (1995) [pdf]
#92Oh, to return to what life was like 23 years ago, when GUI applications were so simple that you could get away with fitting all their work onto a single thread. Nowadays, a great many GUI apps have a lot of data crunching to do in the background. You've really got two options for how to handle that: 1. Be intermittently unresponsive, like iTunes. 2. Do work on a background thread, like decent software. (Intentionally…
Windows NT, OS/2, and BeOS were better, if only the hardware cost cane down and we could ditch this legacy DOS/Win16 code…
Re: Why Threads Are a Bad Idea (1995) [pdf]
#93OK threads aren't "BAD" or "GOOD", threads are a tool to be used correctly. Threads are like a data super-highway and all the incorrect uses of them arise from using them for way to little data. Akin to building a 5 lane highway for 5 cars to pass. A thread has some amazing things of being able to switch an execution very fast (built into things on the CPU level) and memory caching/storing advantages. Aka a thread is…
How is it clever? You cannot have async IO without an event loop. Async IO was a pretty mature technology long before nodejs came out. Netty did this back in 2004. The only special thing about nodejs is that it's culture is to be async by default.
Re: Why Threads Are a Bad Idea (1995) [pdf]
#94Still are. But goroutines are o.k. :)
And they allow you to make the same mistakes you can make with threads.
Don't get me wrong, I love Go. But it does not free you from having to think about what you are doing.
Re: Why Threads Are a Bad Idea (1995) [pdf]
#95Earlier quoted context omitted.
Interesting. Fundamentally, in order to achieve async io, a continuation is necessary. Syntax may hide this (e.g. async/await), or make it apparent as in callbacks/promises. I can't blame JavaScript for not having syntax that makes async pretty. That being said, if we're talking not about IO, but about cpu/memory bound problems... Well I'd be lying if I said it was uncommon in my career to come across people who assu…
You're focusing on performance. Performance is not the world. Parallelism is not the only reason to use cooperating processes. There are other considerations--like task fairness, and isolation. We desperately need more isolation in software.
Re: Why Threads Are a Bad Idea (1995) [pdf]
#96Earlier quoted context omitted.
I don't claim these are "go-to" solutions, but only that there are multiple solutions to pick from. One solution is processes (mentioned in the post). Fork a process which does your computationally expensive thing and then get the result when you are done. For the security minded, we've seen this make a bit of a come back because separate processes can be run with more restrictions and can crash without corrupting th…
> One solution is processes More expensive to start than threads, and far more expensive and complex and restrictive to move data around. Sounds like with the exception of some specific corner cases, threads are a better solution. > Another solution is break up the work and processing in increments Either the tasks aee broken into ridiculously fine-grained bits that are hard to make sense or keep track,or you still g…
These costs, though, are generally trivial compared to the lifecycle costs of dealing with multithreaded code. Isolation in processes greatly enhances debuggability, and it's almost impossible to produce a truly bug-free threaded program. Even a heavily tested threaded program will often break mysteriously when compiled with a different compiler/libraries, or even when seemingly irrelevant code changes are made. It's a tar pit.
Re: Why Threads Are a Bad Idea (1995) [pdf]
#97Earlier quoted context omitted.
I don't claim these are "go-to" solutions, but only that there are multiple solutions to pick from. One solution is processes (mentioned in the post). Fork a process which does your computationally expensive thing and then get the result when you are done. For the security minded, we've seen this make a bit of a come back because separate processes can be run with more restrictions and can crash without corrupting th…
> One solution is processes More expensive to start than threads, and far more expensive and complex and restrictive to move data around. Sounds like with the exception of some specific corner cases, threads are a better solution. > Another solution is break up the work and processing in increments Either the tasks aee broken into ridiculously fine-grained bits that are hard to make sense or keep track,or you still g…
Maybe, but, on Linux, processes and threads are almost the same thing.
Additionally, even where a process is a bit more expensive to create, it is not enough to block the UI thread from being responsive. I have first hand experience with this on different operating systems, including Windows, and it is more than fast enough to keep the UI completely responsive.
> and far more expensive and complex and restrictive to move data around.
Not necessarily. For threading, synchronization patterns are not necessarily simple. (This is why computer science instruction spend time on these principles.)
Furthermore, some languages and frameworks provide really nice IPC mechanisms. Apple's new XPC frameworks are pretty nice and make it pretty easy to do.
> Either the tasks aee broken into ridiculously fine-grained bits that are hard to make sense or keep track,or you still get a blocking UI.
As I mentioned, coroutines make this dirt easy. It principle, this doesn't have to be hard.
> Furthermore, the solution is computationally more expensive.
That doesn't really follow. The underlying task is the where the computation is. You are just moving it, either to a process, a thread, or dividing it up, or something else (e.g. send it to a server to process). At the end of the day, it is the same work, just moved.
Yes, you might need some state flags for breaking up the work, but threading also requires resources such as creating and running the thread, the locks and protecting your shared data, and so forth. There is no free lunch any way you do this.
Re: Why Threads Are a Bad Idea (1995) [pdf]
#98Oh gee I guess I'm a wizard. Lots of systems/embedded programmers roll their eyes at this kind of talk. Threads aren't really that hard. Event queues do have benefits in certain situations. They pair nicely with state machines. You can easily end up in callback hell though, and it is often difficult to integrate some long-running, atomic tasks into your event loop. You end up doing things like having a thread pool, a…
Yes, small careful software teams can make threads work. However, if you start to work with physicists, mathematicians, electrical engineers, and so on who are incredibly smart in their own areas, but who don't have or even value a skill in software, you'll discover they make a real mess out of threaded programs in a way that doesn't happen with separate single-threaded processes.
Re: Why Threads Are a Bad Idea (1995) [pdf]
#99I was not coding in 95, and therefore don’t understand the perspective of the author back then, but it seems clear from the presentation that the culprit was “shared mutable state”, not “threads”. Wasn’t functional programming a thing back then?
LISP was the best-known functional language, although I learned a bit of ML in one of my programming language classes to give us a look at what a functional language looked like. The professor was terrible at explaining functional programming, so I didn't understand it until many years later when I slowly started doing functional-style Javascript and then learning Elixir.
Functional languages really shine under parallel-processing conditions, but that wasn't a big thing at the time. Processors could handle multiple threads, but there was only one core, so only one thing could run at a time. Systems with multiple cores or multiple processors were rare and expensive.
C++ was the dominant language then and all multi-threaded programming (at least all the multi-threaded code I ever saw) used threads with locks to access mutable state shared between threads. No doubt there were some people who had better knowledge, but virtually all software developers at the time were either doing single-threaded code or writing C++ code using threads.
Many languages we use now didn't exist then, and we just knew what was widely used at the time. Haskell existed, but I had never heard of it. Java, C#, Python, Ruby, Go, and Rust weren't around. Javascript was just introduced that year. A lot of stuff was written using languages like C, C++, Ada, and (ugh!) Visual Basic.
It wasn't until many years later (after 2010) did I slowly learn about immutable state and functional programming. Languages had evolved a lot in that time and functional programming overhead no longer mattered now that processors had become so much faster and had started sprouting multiple cores. We also have fastly more memory at our disposal, so we don't have to write code anymore that is super memory-efficient at the expense of everything else. Functional languages aren't performant enough to write an operating system in (and they usually don't allow manual memory management), but they're just fine for most applications.
Functional languages and the concept of immutable state have really flourished since 1995, now that the environment is much more favorable for them. Faster processors and more cores made functional programming and immutable state much more practical to use. I'm so happy that this is the case, because writing multi-threaded code with a shared mutable state was really tough.
Re: Why Threads Are a Bad Idea (1995) [pdf]
#100Earlier quoted context omitted.
Yes, small careful software teams can make threads work. However, if you start to work with physicists, mathematicians, electrical engineers, and so on who are incredibly smart in their own areas, but who don't have or even value a skill in software, you'll discover they make a real mess out of threaded programs in a way that doesn't happen with separate single-threaded processes.
If that's your audience, then you should give them a library/framework/language that hides all the complexity. I'm currently spending a lot of time working on Python Tornado stuff on an embedded device, and I can say that the lack of threads does not substantially reduce the number of ways you can screw things up.
No experience or comment on Python/Tornado. We don't really do a lot of web stuff.
But sure, people can screw things up in lots of ways. However, once a threaded program is screwed up, you really only fix it by starting a new version - it's near impossible to incrementally fix race conditions and dead locks - you can't reliably repeat the bug to debug it. Bugs in non-threaded code can at least be tracked down one by one.