People are messing up any number of things all the time. The more important question is, do you need to risk messing up in a particular situation? I.e. do you need multithreading? In many cases, for example HPC or GUI programming, the answer is yes, you need multithreading to avoid blocking and to get much higher performance.
With a little bit of experience and a bit of care, multithreading isn't _that_ hard. You just need to design for it. You can reduce the number of critical pieces.
I completely disagree with you and I do write performance code (but not specifically HPC) and my current day job is highly async code with a GUI
Are you saying GUIs in general don't need multithreading or just that you think you haven't needed it so far? Or that you use some high-level async framework that hides just the synchronisation bits (at the cost of async type complexity)?
I use a high-level async framework. It works extremely well so far. I do need to add code occasionally, but that's because it's an in-house lib that isn't a year old yet