People: There are solutions to this shit. If you're building a distributed system or need to deal with loss of data regardless, use actor systems (Erlang or Akka). If you need something that's not quite as probabilistic and are willing to handle deadlocks use CSP (Go or Rust). If you need absolute determinism and you're willing to pay for it in performance use SRP (Esterel or possibly maybe at your own risk Céu).
If you need shitstains in your underwear use locks and semaphores.
Agreed. Now days, you should not even think about threads. If you are, you're doing it wrong. You should only be concerning yourself with immutability or not sharing state. Hardly rocket science. Here's how easy it is in Go: https://github.com/Spatially/go-workgroup just write a function and send it data. Done. Granted, to do that distributed requires some thought for the remoting but still not a concern for the developer.
I get the feeling a lot of developers have only ever written one or two very specific kinds of software and think that their experiences generalise to all kinds.
Threading with locks isn't going to go away any time soon no matter how religiously one states their opposition to it. Take the case of mobile or indeed desktop app programming:
• Memory usage is important
• Real-time responsiveness is important
• Avoiding slow operations on the main thread is important
Some consequences of these constraints is that if you have a simple actor like design with a GUI thread (frontend) and a backend thread (network, other expensive operations) you can easily write crappy software. If the GUI needs a bit of data and needs it fast because the user just navigated to a new screen, sending a message to the backend actor and waiting whilst it finishes off whatever task it's doing isn't going to cut it. You need fine grained access to a subset of the data being managed by the backend, and you need it now, without yielding to some other thread that might not get scheduled quickly. And you need to avoid delays due to duplicating a large object graph then garbage collecting that immutable copy or (worse) running out of RAM and having your app be killed by the OS.
In some kinds of web server I've worked on, you're serving a large mostly-but-not-quite immutable data store. That data set must be held in RAM and you cannot have one copy for each thread because that'd not fit into the servers you use. And the data set must be hot-updateable whilst the server is running. You cannot just code around these requirements, they're fundamental to the product.
You can sometimes accept doubling your memory usage so the serving copy can be immutable whilst a new copy is created and updated. but sometimes that just makes you more expensive than your competitors.
There are lots of types of programming where for performance, cost or other reasons, you simply cannot say "shared state is hard so we will never do it". You just have to bite the bullet and do it.
Actors/messaging doesn't imply a remote-backend architecture. It only implies messaging and mutually-exclusive _writable_ state.
GUIs is a poor example as they are inherently single-threaded frontends so performing simultaneous actions is already often implemented utilizing message-passing to backend threads which report back to a single-threaded event-loop. That architecture can be local, backend "threads" or remote processes, as it doesn't much matter to the GUI.
With regard to in-memory persistence, again, you almost certainly would not copy data per thread. For a situation like you're describing, a Redis-like architecture is all you need with a few atomic primitives. But, again, incredibly easy to implement in Go and is certainly _not_ rocket science.
Of course, someone is going to still be using locks, but it's a diminishing number of developers that need to code at that level since there are better higher-level techniques that serve many purposes and protect against many types of errors.
For distributed systems you are supposed to use Erlang with OTP or maybe Akka if you need more speed/JVM. Local and distributed concurrency are nearly indistinguishable when using actors.
If you need shitstains in your underwear use locks and semaphores.