Hacker News new | ask | show | jobs
by btilly 3398 days ago
Short answer, race conditions.

Here is a longer answer. Node currently uses cooperative multi-tasking. Each function call owns the CPU until it gives up the CPU by returning. Therefore all operations are implicitly atomic. Which makes them very easy to reason about.

As soon as you move to multithreading, NOTHING is atomic unless you lock it. You can even have problems with something as simple as:

    globalCounter = globalCounter + 1;
(If one thread is suspended between reading on the RHS and writing on the LHS, another thread can fetch fetch/write the value, and then that update gets lost when the first thread continues execution.)

There have been many cooperative async programming systems in the past. Every one that has moved to preemptive (which multi-threading is) has uncovered a lot of subtle, hard to spot, and hard to fix bugs because of losing implicit atomic guarantees.

So you go back to the safe solution of locking everything. But now locking/unlocking takes away a bunch of performance, limits parallelism, and creates the possibility for things like deadlocks. And now you might as well not bother with multiple CPUs! (See Python's GIL for a well-known example of this result.)

The challenge therefore is how to add some pre-emptive multitasking while avoiding creating too many unexpected nasty race conditions.