This article is a bit dated. It's all about locks that aren't directly connected to the data they lock. With the advent of Rust, people are finally getting that "what locks what" is something the language should address. C/C++ locking is a legacy of the "that's an operating system problem" era of locking.
It's not just a safety issue. If you need to fence something, it helps if the compiler knows what to fence.
Tieing locks to data is not a new concept. Java provides an intrinsic lock on every object (along with special syntax around acquiring/releasing this lock)
It's not new at all. It goes back to Brinch Hansen and Hoare in the early 1970s.[1] Modula and Ada had it. But the C/C++ crowd tends not to know about it, because Unix and C did not originally have threads and concurrency was a retrofit.
I almost always use mutexes and condition variables. Almost never semaphores. I wholeheartedly agree with the post about recursive mutexes being bad. I find it always a indication of bad design and/or ”lets make this code multi-thread safe by slapping a giant big mutex around all entry points”
Allen B. Downey's "The Little Book of Semaphores" is a great resource if you want to go a bit further on understanding how to use these things and design solutions to synchronization problems. It's available for free: https://greenteapress.com/wp/semaphores/
https://sourceware.org/bugzilla/show_bug.cgi?id=12674
now once upon a time this semaphore issue almost drove me crazy. beware of the semaphore! (at least on older linux systems; they fixed this one in 2015 - but it takes time for glibc changes to make it into a distro)
I'm starting to like async as in libuv and JS. I don't know what people think of JS but I've done condition variables (Java) and semaphores through shared memory and I actually think async is going to rule long term. Yeah, JS is not procedural. But if you don't fight it it's actually quite elegant. And I'm an old. If I can learn a new way of thinking you can too. And by "don't fight it" I mean no Promises or async / await. Those are just window dressing (and worthless IMO). Just use callbacks. Attach them to an object if you want a single object to pass around like you might with a Promise (that's all a Promise is anyway). You will need to use an arrow function to set "this" though.
This article is a bit dated. It's all about locks that aren't directly connected to the data they lock. With the advent of Rust, people are finally getting that "what locks what" is something the language should address. C/C++ locking is a legacy of the "that's an operating system problem" era of locking.
It's not just a safety issue. If you need to fence something, it helps if the compiler knows what to fence.