5 ms·
This article is nearly 2 decades old and gives very bad advice for multithreaded c++ programming. To a first approximation, volatile should never be used for mu
by aarongolliver 7y ago
This article is nearly 2 decades old and gives very bad advice for multithreaded c++ programming. To a first approximation, volatile should never be used for multithreading safety.
- mehrdadn 7y agoThat 2-decade-old article took some 5+ pages to thoroughly explain its ideas. Turns out it was (and still is) pretty compelling, and the changes in these past 2 decades don't really affect what it's saying. You, who've surely carefully read the article, understood it in its entirety, and played around with the notion to get a feel for its upsides and downsides, very insightfully reduced it all down to "very bad advice" with zero elaboration. You find that compelling? I would be careful with those "first-order approximations".
- ori_b 7y agoVolatile is not a memory barrier. Different threads can observe reordered accesses regardless of volatile. There's a reason that it's been proposed for removal (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1152r0.html http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p115...)
- mehrdadn 7y agoWhere did you see the article claim it was a memory barrier?
- aarongolliver 7y agoIt doesn't say it's a memory barrier, but it absolutely has to be for the code to work. I agree I should be careful with "first-order approximations", but honestly I was being gentle because I do love drdobbs. But all of the things it talked about have been replaced with things that aren't broken in subtle and hard to debug way. Volatile simply cannot be used a general purpose, portable, synchronization primitive.
- mehrdadn 7y ago> It doesn't say it's a memory barrier, but it absolutely has to be for the code to work. No, it doesn't say it because it's not trying to make the point that you assume it's trying to make. Honest question: did you fully read and digest the article before commenting? If so, tell me on precisely which line you saw a lack of a memory barrier causing a problem (describe the race condition & bug you found) and explain how exactly you found that to undermine the point of the article.
- deleted 7y ago[deleted]
- deleted 7y ago[deleted]
- BeeOnRope 7y agoYou don't even need to read the whole article to see the GP's point: the very first example with flag_ is concurrent, unsynchronized access to a shared volatile, and the article promotes it as "the right way". Yes, it goes on to elaborate on a basically unrelated use of volatile to control access to member functions on classes, which deserves a separate discussion - but you don't even need to get past the first few paragraphs to see that it promulgates the idea that broken makes concurrent access safe. It doesn't.
- ori_b 7y agoThe code in the article requires memory barriers. It doesn't have them. It's broken code. The author is using volatile as though it implied a barrier.
- mehrdadn 7y ago> The code in the article requires memory barriers. It doesn't have them. It's broken code. > The author is using volatile as though it implied a barrier. No, you're just not reading the article. Please go read the article. And I don't mean skim. I mean actually read it with the assumption that you have zero clue what it's going to say, because that's more accurate than your current assumption. Then if you still think you're correct, please explain to exactly which line(s) in the code are broken and how precisely that actually undermines the points the article has been making. You will struggle to do this. In case it helps, for your reference: the author isn't, and never was, a random C++ dummy.
- ori_b 7y ago> Just like its better-known counterpart const, volatile is a type modifier. It's intended to be used in conjunction with variables that are accessed and modified in different threads. Simply not true. It has limited use with memory mapped I/O (although even there it misses necessary guarantees), but is not intended to work with threads. > So all you have to do to make Gadget's Wait/Wakeup combo work is to qualify flag_ appropriately: class Gadget { public: ... as above ... private: volatile bool flag_; }; Is not correct, and will not work reliably. I spent some time working with Andrei at Facebook, and he's a smart guy, but this article is wrong. Don't do what he says here. Volatile needs to go away.
- mehrdadn 7y agoHe's describing the current state of affairs in that statement and providing background context, which was that volatile was seen as a solution to the memory barrier issue at that time, which we know to be incorrect now, but which was the closest approximation the C++ standard had to a half-solution at the time. That's NOT the point of the aricle, it's just background context for 2001 readers. There's a whole article after that which does not tell you to use volatile that way, and the entire reason I posted it was that part. Did you read past that paragraph at all, till the end? Did you understand what the article was actually trying to tell you, or did you just try to find a code snippet that didn't look right without bothering to read the full article? Did you see he literally advises you in the end: "DON'T use volatile directly with primitive types"? The entire point of the article is to tell you about a use case that is explicitly not the one you're imagining.