Live data from Hacker News

Why Threads Are a Bad Idea (1995) [pdf]

cc.gatech.edu

31–40 of 103 posts

Re: Why Threads Are a Bad Idea (1995) [pdf]

#31
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 new project back around then to build a system for deep caching of web sites to give time consistent access offline. I implemented as a web proxy with an online/offline button. As you browsed web sites, it would crawl recursively following a set of rules. The intent was to precache content near what you already explicitly accessed, to make it available offline later on (we called this the "detachable web").

While not the primary purpose of our project, I put together a demo to optimize the Alta Vista search results page, which at the bottom only had a "Next" button (unlike the "1 2 3 4 5..." you see at places like Google today). When you clicked "Next", it took Alta Vista a few seconds (4-5) to return the next page of search results. My system would prefetch the 10 pages of results by POSTing the "Next" for you, basically while you were still reading the first page resuls. The result was "Next" became instantaneous. Again, this is not why we built this system; this was just one novel approach I used it for.

I mentioned all this because the entire project was implemented in Tcl. Being influenced by the lack of thread support in Tcl and by the paper mentioned in the OP, my project utilized a event-driven model for everything, since every inbound user require could fire off dozens of background fetches, all of which needed to be done in parallel. Events (and continuations) worked well for this. I have a paper up from the 5th Tcl/Tk workshop:

https://www.usenix.org/conference/5th-annual-tcltk-workshop-...

I had used for the project Tcl because it let me support all three prevalent platforms of the time: UNIX, Windows 95, and MacOS 9. Day-to-day work was done on FreeBSD.

I think have some commentary in the paper on the effects of the event-driven approach. What's funny is that I was taken off the project for v2, which the team then decided would be written in Java using threads, because, well, Tcl wasn't mainstream enough. In 1997, Java was the rage. The downside is that they could never get v2 working reliably enough because of the explosion in memory and processing power it required to accomplish the same work. In Tcl, having 60 traversals active when it was just 60 continuations (events) just worked. In contrast, the Java implementation needed 2-3 threads per traversal, and it just couldn't scale up to that.

Re: Why Threads Are a Bad Idea (1995) [pdf]

#32
post #2

> Only use threads where true CPU concurrency is needed. This is the case much more often now than it was in 1995.

Not just "more often" but essential. We've been at four hardware threads for a decade now, and we're just entering a new era where increasing the number of CPU cores is becoming a marketing tactic.

Re: Why Threads Are a Bad Idea (1995) [pdf]

#33

Oh 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…

If your state machine event handlers are non-blocking, then the thread pool is the same size as the number of available hyperthreads. That's not hard either. And, as observed elsewhere, it becomes impossible to screw up. That's a powerful property, and makes it possible for non-embedded 'normal' folks to write correct code in this space.

Re: Why Threads Are a Bad Idea (1995) [pdf]

#34
post #4
post #3

The source of the article, Sun, is interesting. I guess the author knew what was about to be foisted upon the world. Kudos for trying to warn us. (I remember reading Novell and OS/2 documentation in the late 80s / early 90s about threads and recoiling in horror. Of course, all real men must use threads, cuz they’re faster, even if stupefyingly dangerous)

John Ousterhout is the inventor of the Tcl language.

[deleted]

Re: Why Threads Are a Bad Idea (1995) [pdf]

#36
I 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?

Re: Why Threads Are a Bad Idea (1995) [pdf]

#37

Oh 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]

#38

Oh 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…

There's even a course from GA Tech (Intro to Operating Systems, publicly available on Udacity) that covers how to use threads safely and sanely. I went in knowing nothing but terror from a failed experiment in naive multithreading and came out wanting to apply threads to everything. Maybe not quite the right approach, but I at least feel vastly more confident with keeping them manageable. Like you say, managing how and when to lock is the key.

Re: Why Threads Are a Bad Idea (1995) [pdf]

#39
post #36

I 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?

As I remember things, for the most part, no. Which is to say that of course there were people doing FP (Lisp is old as the hills & Haskell was launched in 1990) but my perception was that it wasn’t remotely mainstream in the way it is now.

Re: Why Threads Are a Bad Idea (1995) [pdf]

#40

Oh 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…

Systems/embedded programmers roll their eyes at this kind of talk because they usually control (or at least have visibility into) all of the code that goes into their stack. Threads aren't that hard under these conditions.

The main problem with threads is that they're non-composable: the set of locks that a thread holds is basically an implicit dynamically-scoped global variable that can affect the correctness of the program. If you call into an opaque third-party library, you have no idea what locks it may take. If it then invokes a callback into your own code, and you then call back into the library, there is a good chance that your callback will block on some lock that a framework thread holds, that framework thread will block on a lock you hold, and then the code that releases that lock will never execute. Deadlock.

If you control all of the code in your project, this does not affect you: define an order in which locks must be acquired and released and stick to it. If all of your dependencies have no shared data and never acquire locks themselves, this does not affect you (and indeed, this is recommended best practice for reusable libraries). If you never call back into third-party libraries from callbacks, this does not affect you, but it severely limits the set of programs you can write. If all of your dependencies thoroughly document the locks they take and in which order, this affects you but you can at least work around the problem areas and avoid surprise deadlocks.

Most application developers do not work under conditions where any of these are true, let alone all of them. Application development today largely consists of cobbling together third-party libraries and frameworks, many of which are undocumented, many of which are thread-unsafe, and many of which spawn their own threads and invoke callbacks on an arbitrary thread.

Post reply on HN