zne*_*eak 4 c c++ multithreading
我想知道编译器有什么保证可以确保对内存的线程写入在其他线程中具有可见效果.
我知道无数的情况,这是有问题的,我敢肯定,如果你有兴趣回答你也知道它,但请关注我将要呈现的案件.
更确切地说,我担心可能导致线程丢失其他线程完成的内存更新的情况.我不关心(此时)更新是非原子的还是非常同步的:只要相关的线程注意到更改,我会很高兴.
我希望编译器区分两种变量访问:
例如,如果您使用此代码段:
void sleepingbeauty()
{
int i = 1;
while (i) sleep(1);
}
Run Code Online (Sandbox Code Playgroud)
既然i是本地的,我认为我的编译器可以优化它,只是让沉睡的美丽陷入永恒的沉睡.
void onedaymyprincewillcome(int* i);
void sleepingbeauty()
{
int i = 1;
onedaymyprincewillcome(&i);
while (i) sleep(1);
}
Run Code Online (Sandbox Code Playgroud)
既然i是本地的,但是它的地址被接受并传递给另一个函数,我假设我的编译器现在知道它是一个"可寻址的"变量,并生成内存读取以确保可能有一天王子会来.
int i = 1;
void sleepingbeauty()
{
while (i) sleep(1);
}
Run Code Online (Sandbox Code Playgroud)
由于i是全局的,我假设我的编译器知道变量有一个地址,并将生成读取而不是缓存该值.
void sleepingbeauty(int* ptr)
{
*ptr = 1;
while (*ptr) sleep(1);
}
Run Code Online (Sandbox Code Playgroud)
我希望dereference运算符足够明确,让我的编译器在每次循环迭代时生成一个内存读取.
我很确定这是生产中每个C和C++编译器使用的内存访问模型,但我认为没有任何保证.事实上,C++ 03甚至对线程的存在视而不见,所以这个问题在标准时甚至都没有意义.不过我对C不太确定.
是否有一些文件指明我是对还是错?我知道这些都是泥泞的水域,因为这些可能不符合标准,对我来说这似乎是一个重要的问题.
除了编译器生成读取之外,我还担心CPU缓存在技术上可能会保留一个过时的值,即使我的编译器尽力使读取和写入,值也不会在线程之间同步.这会发生吗?
访问不一定具有地址的变量.
所有变量都必须具有地址(来自语言的预期 - 允许编译器避免在可能的情况下给出地址,但是在语言内部不可见).这是一个副作用,一切都必须"可以",所有东西都有一个地址 - 即使空类通常具有至少一个大小,char以便可以创建一个指针.
因为我是一个本地的,但是它的地址被传递给另一个函数,我假设我的编译器现在知道它是一个"可寻址的"变量,并生成内存读取以确保可能有一天王子会来.
这取决于的内容onedaymyprincewillcome.编译器可以根据需要内联该函数,但仍然不进行内存读取.
由于我是全局的,我假设我的编译器知道变量有一个地址并将生成读取.
是的,但是如果有读取它真的没关系.这些读取可能只是缓存在当前的本地CPU核心上,而不是实际上一直回到主内存.你需要这样的内存屏障,没有C++编译器会为你做这件事.
我希望dereference运算符足够明确,让我的编译器在每次循环迭代时生成一个内存读取.
不 - 不是必需的.该函数可以内联,这将允许编译器在需要时完全删除这些内容.
标准中唯一允许您控制此类wrt线程的语言特性,这只volatile需要编译器生成读取.这并不意味着价值将是一致的,因为CPU缓存问题 - 你需要内存障碍.
如果你需要真正的多线程正确性,那么你将使用一些特定于平台的库来生成内存障碍等等,或者你需要一个支持的C++ 0x编译器std::atomic,它确实满足了这些要求关于变量显式.