You have a Common Lisp program running, multiple threads listening for network connections, others processing data in the background. You were really careful making sure that there are no data access conflicts. Concurrency, check. You use Emacs and SLIME to connect to your server, inspect its state. Interactivity, check. You realize a global hash table contains an incorrect value; no problem, just evaluate a simple REMHASH expression. Mutability, check. Unfortunately another thread happens to read the hash table while the form is being evaluated. Game over.
You want concurrency, loosely defined as “having multiple execution threads making progress in the same unit of time”, because it allows for faster programs, processing more data faster. But now your programs are much more complex because you need to protect data accesses to avoid deadlocks, starvation, memory corruption and other unpleasant consequences.
You want interactivity, because it is so convenient to be able to inspect and update the state of your program at any time. But now you can access any data whenever you want, data that may be read or written by concurrent threads.
You want mutability, because it is practical.
But you cannot have it all.
Dropping interactivity
The most popular choice is to drop interactivity: since there is no one to randomly access runtime data, there are no concurrency issues. C, Rust, Go, the list of languages that go this way is long.
You are efficient and safe, but you lose the ability to work with your systems during execution. Frustrating during development, or to debug and fix complex systems where restarting is not always an option.
Dropping concurrency
You can still have multiple threads of course, but nothing in your program can be read or written at the same time. Python and Ruby are good examples of languages that drop concurrency by using a GIL (Global Interpreter Lock).
... continue reading