`volatile` to sync variable between threads

只愿长相守 提交于 2021-02-07 06:27:05

问题


I have a variable int foo that is accessed from two threads. Assuming I have no race-condition issues (access is protected by a mutex, all operations are atomic, or whatever other method to protect from race conditions), there is still the issue of "register caching" (for lack of a better name), where the compiler may assume that if the variable is read twice without being written in between, it is the same value, and so may "optimize" away things like:

while(foo) { // <-may be optimized to if(foo) while(1)
  do-something-that-doesn't-involve-foo;
}

or

if(foo) // becomes something like (my assembly is very rusty): mov ebx, [foo]; cmp ebx, 0; jz label;
  do-something-that-doesn't-involve-foo;
do-something-else-that-doesn't-involve-foo;
if(foo) // <-may be optimized to jz label2;
  do-something;

does marking foo as volatile solve this issue? Are changes from one thread guaranteed to reach the other thread?

If not, what other way is there to do this? I need a solution for Linux/Windows (possibly separate solutions), no C++11.


回答1:


What you need are memory barriers.

MemoryBarrier();

or

__sync_synchronize();

Edit: I've bolded the interesting part and here's the link to the wiki article (http://en.wikipedia.org/wiki/Memory_barrier#cite_note-1) and the associated reference (http://www.rdrop.com/users/paulmck/scalability/paper/whymb.2010.07.23a.pdf)

Here's the answer to your other question (from wikipedia): In C and C++, the volatile keyword was intended to allow C and C++ programs to directly access memory-mapped I/O. Memory-mapped I/O generally requires that the reads and writes specified in source code happen in the exact order specified with no omissions. Omissions or reorderings of reads and writes by the compiler would break the communication between the program and the device accessed by memory-mapped I/O. A C or C++ compiler may not reorder reads and writes to volatile memory locations, nor may it omit a read or write to a volatile memory location. The keyword volatile does not guarantee a memory barrier to enforce cache-consistency. Therefore the use of "volatile" alone is not sufficient to use a variable for inter-thread communication on all systems and processors[1]

Check this one out, it provides great explanations on the subject: http://channel9.msdn.com/Shows/Going+Deep/Cpp-and-Beyond-2012-Herb-Sutter-atomic-Weapons-1-of-2 http://channel9.msdn.com/Shows/Going+Deep/Cpp-and-Beyond-2012-Herb-Sutter-atomic-Weapons-2-of-2




回答2:


If access is protected by a mutex, you do not have any issue to worry about. The volatile keyword is useless here. A mutex is a full memory barrier and thus no object whose address could be externally visible can be cached across the mutex lock or unlock calls.




回答3:


The volatile keyword was originally introduced to indicate that the value can be changed by the hardware. This happens when hardware device has memory mapped registers or memory buffers. The right approach is to use it only for this purpose.

All modern synchronization language constructs and synchronization libraries are not using this keyword. Application level programmers should do the same thing.



来源:https://stackoverflow.com/questions/18135116/volatile-to-sync-variable-between-threads

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!