Do I need to protect this variable with a lock?

后端 未结 6 1230
天涯浪人
天涯浪人 2021-02-15 11:58

so I have a boolean type in C++ on a multiprocessor machine. The variable starts out life as true, and then there are a few threads, any one or more of which might write it to b

相关标签:
6条回答
  • 2021-02-15 12:36

    For a bool, the answer is generally no, a mutex is not needed, but (as Michael E noted) anything could happen, so you likely need to understand more about your arch before making such a decision. Another note: the code might still need a lock around the overall logic associated with the bool, especially if the bool is read more than once in the course of a routine's logic.

    Some great blogs I read to keep me on my multithreaded toes:

    http://blogs.msdn.com/b/nativeconcurrency/

    http://herbsutter.com/2009/04/20/effective-concurrency-use-thread-pools-correctly-keep-tasks-short-and-nonblocking/

    best regards,

    0 讨论(0)
  • 2021-02-15 12:37

    If only you're checking the state of the variable and setting it to false in one direction ever, there's not much to worry about except that some of the threads may be a little late to see the variable is already set to false. (this may be overcome to some degree by the use of 'volatile' keyword.) Then two threads may set it to false, which is no problem since the variable is set to a single value in one direction. Let's say boolean write to the memory location is not guaranteed to be atomic, what's the harm? The final value they both will write is the same.

    Still, you would have to use a method of locking if:

    • Value setting is not one-direction only: you set it to false, then back to true, then false again, etc.
    • You take some dependent action on the information which thread had set the value to false. Because there obviously may be two winners.
    0 讨论(0)
  • 2021-02-15 12:38

    It's an easy way to break things. With a boolean, you may be ok most of the time, but are provided no guarantees.

    You have two options: use a mutex (lock), or use atomic primitives. Atomic primitives will utilize hardware instructions to do the test and set operations in a thread-safe fashion without requiring an actual mutex and are a lighter-weight solution. The GNU compiler provides access to atomic operations via architecture-specific extensions. There are also portable atomic operation libraries floating around; the Glib C library provides atomic operations that fall back to using a mutex if atomic primitives are not available, although it is a fairly heavy library with many other features as well.

    There is the Boost.Atomic library which abstracts atomic operations for C++; based on its name, it looks like it is aiming to be incorporated into the Boost C++ library collection but hasn't yet made it.

    0 讨论(0)
  • 2021-02-15 12:49

    You are asking about two things.

    First you are asking about atomicity of bool assignment. No there is no guarantee that boolean assignment will be atomic operation. In practice it usually is, but you shouldn't rely on this. Some strange architecture may implement bool assignment in many machine instructions...

    Secondary you are asking about corruption of data due to parallel writes - in practice transport from CPU to memory is done by a bus, which almost always contains more bits than primitive types you are working on. So such corruption may happen for very strange architecture or when working on big numbers (not supported by the system natively). In practice you will usually get 3 or 7. But again, you can't rely on it.

    To conclude this - you need a lock.

    0 讨论(0)
  • 2021-02-15 12:52

    On most commodity hardware a single word reads/writes are atomic, so no, two (or more) competing writes (and reads) to the same memory location are not going to corrupt the value. What is important here is cache coherence between CPUs.

    Again, on commodity hardware you might get away with just marking that single boolean variable volatile (which has been declared useless for concurrent programming btw) to prevent compiler from optimizing it out into a register, but only if you really don't care about the order of writes.

    Let me re-iterate this with a check-list:

    • Are you ready do lose some updates to that boolean?
    • Are you sure no other memory updates that come before the boolean flip in the source code but might get reordered after that flip are going to mess things up?
    • Are you sure you don't care about order of events in your application?

    If you have three strong "yes" answers, you might get away with not protecting that flag. Still consider inserting acquire memory barrier before reading the variable, and release memory barrier before writing it. My suggestion though would be to re-think the design, and lay out clear synchronous inter-thread communications and event sequencing.

    Hope this helps.

    0 讨论(0)
  • 2021-02-15 12:53

    On most commodity hardware single word read and writes are not atomic operations; remember you have virtual memory machines here and either of those operations might cause a page fault.

    In more general terms you'll probably find it easier and quicker to use mutexes as a matter of routine than scratch your head wondering if you are going to get away without one this time. Adding one where it isn't necessary doesn't cause a bug; leaving one out where it is might.

    0 讨论(0)
提交回复
热议问题