I got quite frustrated when I read this article. That's because this article, and the many others like this, confuse the real issue.
This article, and those like it, all state that the problem with multi-threading and synchronization is inherent to the programing paradigm/language/architecture you're using:
> "Buggy multi-threaded code creates race conditions, which are the most dangerous and time-consuming class of bugs in software"
> "because the traditional synchronization primitives are inadequate for large-scale systems."
Ok. Fair enough, now tell us why that is so.
I get quite annoyed when the author then proceeds to turn it all around by saying this:
> "Locks don’t lend themselves to these sorts of elegant principles. The programmer needs to scope the lock just right so as to protect the data from races, while simultaneously avoiding (a) the deadlocks that arise from overlapping locks and (b) the erasure of parallelism that arise from megalocks. The resulting invariants end up being documented in comments:"
> "And so on. When that code is undergoing frequent changes by multiple people, the chances of it being correct and the comments being up to date are slim."
Implying that the real problem with locks/threading/synchronization is actually communication, proper documentation discipline, programmer skill (soft and hard).
Of-course I'm not saying that the process of using primitive synchronization methods can't be abstracted over to make it easier to write _proper_ multi threaded code. It's just that this really feels like subjective politicking very much like the aversion to (proper use of) goto() in C/C++ code.
This made me think. I can't actually agree that it's a matter of language primitives. It's very much about the logical complexity of sharing anything. It seems to be a fundamental, recurring theme in CS, data and logic. In a single thread, in imperative language, there is a sequential list of logical steps and manipulation of data, or state. With two or more threads, you have multiple sequence of statements, but they can try to manipulate same data, it's effectively mashing two sequences together in random order! If that is what you want to do, I don't see anything you can really do to make it not rocket science. I'm sure it can be made easier by using some safer primitives for data access, but I don't see how the high level logical races can be made eliminated. As in, a language can eliminate an object being deleted when it's going to be still accessed, but it can't eliminate a student getting an F at midnight while his homework program is still being tested.
This article, and those like it, all state that the problem with multi-threading and synchronization is inherent to the programing paradigm/language/architecture you're using:
> "Buggy multi-threaded code creates race conditions, which are the most dangerous and time-consuming class of bugs in software"
> "because the traditional synchronization primitives are inadequate for large-scale systems."
Ok. Fair enough, now tell us why that is so.
I get quite annoyed when the author then proceeds to turn it all around by saying this:
> "Locks don’t lend themselves to these sorts of elegant principles. The programmer needs to scope the lock just right so as to protect the data from races, while simultaneously avoiding (a) the deadlocks that arise from overlapping locks and (b) the erasure of parallelism that arise from megalocks. The resulting invariants end up being documented in comments:"
> "And so on. When that code is undergoing frequent changes by multiple people, the chances of it being correct and the comments being up to date are slim."
Implying that the real problem with locks/threading/synchronization is actually communication, proper documentation discipline, programmer skill (soft and hard).
Of-course I'm not saying that the process of using primitive synchronization methods can't be abstracted over to make it easier to write _proper_ multi threaded code. It's just that this really feels like subjective politicking very much like the aversion to (proper use of) goto() in C/C++ code.