The Stack is a global variable.
The reason that programmers feel that "multitasking is hard" is due to the accidental complexity caused by using an implicit global variable.
Causes of Accidental Complexity
This feeling that "multitasking is hard" has at least two causes:
- Not making everything explicit. In the case of CALL/RETURN-based programs (e.g. just about every program today), the stack is implicit and hidden under the covers by most PLs (programming languages). To make matters worse, hardware supports and encourages the use of the stack as a global variable.
- Using the wrong paradigm. Most PLs encourage the use of the synchronous paradigm (e.g. CALL/RETURN using an implicit stack). Memory sharing is encouraged in the synchronous paradigm. Multitasking, though, is inherently asynchronous. Building multitasking in a synchronous paradigm is possible, but leads to accidental complexity, e.g. thread safety concerns arise only due to the sharing of memory, CALL/RETURN uses a global variable, etc. The synchronous paradigm is useful for building calculators - functions with exactly one set of synchronous inputs and exactly one set of synchronous outputs. Calculators are functions that expunge the notion of time. On the other hand, asynchronous computation, e.g. the internet, involves functions of time (aka history) and, generally, does not share memory. In the asynchronous paradigm, inputs and outputs are not synchronized and may be delivered at different points in time. Additionally, one set of inputs does not guarantee only one set of outputs - asynchronous components might produce 0, 1, or more outputs for every input. Timeouts must be made explicit, lest they appear to generate outputs when there have been 0 inputs.