Do I need to protect this variable with a lock?

so I have a boolean type in C ++ on a multiprocessor machine. A variable begins with life as truth, and then there are several flows, any of which can spell it as false.

At the same time, these threads can also read this variable to check its state. I don’t care if the reading of this variable is synchronized with any of the records, each of them occurs in different places in the code, and it does not matter whether it comes before or after any particular record. Now I need a lock for this boolean?

The only way I need a lock is if at a very low level the memory can be damaged by two competing entries. If, for example, the assembly instruction on processor A writes 0 to a byte that represents a logical value, while processor B does the same ... and instead of writing 0, the memory ends with a value of 22 or something. It might ruin something.

So, in general, if proc A writes 3 to a memory location, and proc B writes 7 without synchronization, I am sure that in the end you will get at least 3 or 7? Or is it easy to break memory?

Edit:

Thanks for the comments guys. Additional information: in the program, of course, there is synchronization. To summarize, the corresponding flag indicates that a specific memory pool is "dirty" (it is necessary to compact). Any thread can therefore decide to set this flag to false (this means the pool is dirty). For example, freeing memory from a pool makes it dirty. Any thread can also read this flag and set another flag to signal the need for cleaning - this check is performed when the memory is allocated from the pool, cleaning is signaled if we have little memory. Somewhere in my main critical section between iterations, where each thread goes to look for more data to process, I will have threads checking this second flag, and do something suitable to make sure that: all other add-ons finish their current iteration , one thread clears the memory, sets the first flag back to true (as it is not dirty in the pool), returns the second flag to false, and then frees all threads again.

Therefore, I do not think that I need a lock, because: a lock ensures that the record does not happen at the same time as another record or reading. But who cares until the hardware fails me, the worst case scenario is that reading randomly before or after writing is the same as if I protected it with a lock, then we would really be sure that this happened before or after ...

I think the same argument applies to the second character mentioned above.

+7
c ++ synchronization
source share
6 answers

If you only check the state of a variable and set it to false in one direction, you have nothing to worry about, except that some of the threads may suspect a little that the variable is already set to false (this may be to some extent overcome by using the "volatile" keyword.) Then, two threads can set to false, which is not a problem, since the variable is set to the same value in one direction. Let them say that a logical record in a memory cell is not guaranteed atomic, what harm? The final meaning that they both will write will be the same.

However, you will need to use the lock method if:

  • The value is not only one-sided: you set it to false, and then back to true, then false again, etc.
  • You take some kind of dependent action on the information in which the thread set to false. Because, obviously, there can be two winners.
+7
source share

In most commercial devices, a single reads / write word is atomic, so no, two (or more) competing records (and reads) in the same memory location will not damage the value. The cache coherency between the CPUs is important here.

Again, on commodity equipment, you can leave by simply noting that the only logical variable is volatile (which was declared useless for btw concurrent programming) to prevent the compiler from being optimized to register , but only if you really don't like the order .

Let me repeat it with a checklist:

  • Are you ready to lose some updates for this boolean?
  • Are you sure that there are no other memory updates that appear before a boolean flip in the source code, but can be reordered after this flip ruins everything?
  • Are you sure you are not interested in the order of events in your application?

If you have three strong yes answers, you can leave without defending this flag. Still consider inserting memory capture before reading the variable and freeing the memory barrier before writing. My guess, however, was to rethink the design and lay out clear, synchronous, inter-threaded communications and a sequence of events.

Hope this helps.

+9
source share

This is an easy way to break things. With logical, you can be fine in most cases, but no guarantees are provided.

You have two options: using a mutex (lock) or using atomic primitives. Atomic primitives will use hardware instructions to run the test and set up operations in thread safe mode without requiring an actual mutex and an easier solution. The GNU compiler provides access to atomic operations through architecture-specific extensions. There are also portable atomic operating libraries; Glib C library provides atomic operations that revert to using the mutex if atomic primitives are unavailable, although this is a pretty heavy library with many other features.

There is a Boost.Atomic library that abstracts atomic operations for C ++; based on its name, it looks like it aims to be included in the Boost C ++ library, but hasn't done it yet.

+3
source share

For bool, as a rule, there is no answer, the mutex is not needed, but (as Michael E noted), something can happen, so you most likely need to learn more about your arch before making such a decision. One more note: for the code, you may still need to block the general logic associated with bool, especially if bool is read more than once during normal logic.

Some great blogs I've read to keep me on my multi-threaded socks:

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

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

Best wishes,

+1
source share

You ask about two things.

First, you ask about the atomicity of the bool assignment. There is no guarantee that the logical assignment will be atomic. In practice, this is common, but you should not rely on it. Some weird architecture can implement the bool assignment in many machine instructions ...

The second time you ask about data corruption due to parallel writing - in practice, the transfer from the CPU to the memory is done using the bus, which almost always contains more bits than the primitive types you are working on. Thus, such corruption can occur for a very strange architecture or when working with large numbers (not supported by the system initially). In practice, you usually get 3 or 7. But then again, you cannot rely on it.

In conclusion: you need a castle.

+1
source share

In most commodity apparatuses, the single word read and write are not atomic operations; remember that you have machines with virtual memory, and any of these operations may cause a page error.

More generally, you will probably find it easier and faster to use mutexes in a routine mode than to scratch your head if you want to leave without it this time. Adding one where it is not needed does not cause an error; leaving him where possible.

+1
source share

All Articles