C++ – Synchronizing access to variable

cmemorymulticoremultithreadingparallel-processing

I need to provide synchronization to some members of a structure.
If the structure is something like this

struct SharedStruct {
    int Value1;
    int Value2;
}

and I have a global variable

SharedStruct obj;  

I want that the write from a processor

 obj.Value1 = 5; // Processor B

to be immediately visible to the other processors, so that when I test the value

 if(obj.Value1 == 5) { DoSmth(); } // Processor A
 else DoSmthElse();   

to get the new value, not some old value from the cache.
First I though that if I use volatile when writing/reading the values, it is enough. But I read that volatile can't solve this kind o issues.
The members are guaranteed to be properly aligned on 2/4/8 byte boundaries, and writes should be atomic in this case, but I'm not sure how the cache could interfere with this.
Using memory barriers (mfence, sfence, etc.) would be enough ? Or some interlocked operations are required ?
Or maybe something like

lock mov addr, REGISTER  

?
The easiest would obviously be some locking mechanism, but speed is critical and can't afford locks šŸ™

Edit
Maybe I should clarify a bit. The value is set only once (behaves like a flag). All the other threads need just to read it. That's why I think that it may be a way to force the read of this new value without using locks.

Thanks in advance!

Best Answer

All the other answers here seem to hand wave about the complexities of updating shared variables using mutexes, etc. It is true that you want the update to be atomic. And you could use various OS primitives to ensure that, and that would be good programming style.

However, on most modern processors (certainly the x86), writes of small, aligned scalar values is atomic and immediately visible to other processors due to cache coherency. So in this special case, you don't need all the synchronizing junk; the hardware does the atomic operation for you. Certainly this is safe with 4 byte values (e.g., "int" in 32 bit C compilers).

So you could just initialize Value1 with an uninteresting value (say 0) before you start the parallel threads, and simply write other values there. If the question is exiting the loop on a fixed value (e.g., if value1 == 5) this will be perfectly safe.

If you insist on capturing the first value written, this won't work. But if you have a parallel set of threads, and any value written other than the uninteresting one will do, this is also fine.

Related Topic