我的问题是,我们仍然需要将这些计数器声明为volatile,以便编译器在进行优化时不会使其松动.@H_403_3@
或者编译器考虑到计数器被互斥体保护.@H_403_3@
我明白互斥是用于同步的运行时机制,“volatile”关键字是一个编译时指示,编译器在进行优化时做正确的 *** 作.@H_403_3@
问候,
-Jay.@H_403_3@解决方法 这里有两个基本上无关的项目,总是困惑.
>挥发性
线程,锁,内存障碍等@H_403_3@
volatile用于告诉编译器生成代码以从内存中读取变量,而不是从寄存器读取变量.并且不要重新排序代码.一般来说,不优化或采取“快捷”.@H_403_3@
内存障碍(由互斥锁,锁等提供)在Herb Sutter引用另一个答案中,是为了防止cpu重新排序读/写存储器请求,而不管编译器如何做.即不要优化,不要采取快捷方式 – 在cpu级别.@H_403_3@
类似的,但实际上是非常不同的事情.@H_403_3@
在你的情况下,在大多数锁定情况下,volatile不是必需的,这是因为为了锁定而进行的函数调用.即:@H_403_3@
正常功能调用影响优化:@H_403_3@
external voID library_func(); // from some external libraryglobal int x;int f(){ x = 2; library_func(); return x; // x is reloaded because it may have changed}
除非编译器可以检查library_func()并确定它不触及x,否则它将在返回时重新读取x.这甚至没有波动.@H_403_3@
线程:@H_403_3@
int f(SomeObject & obj){ int temp1; int temp2; int temp3; int temp1 = obj.x; lock(obj.mutex); // really should use RAII temp2 = obj.x; temp3 = obj.x; unlock(obj.mutex); return temp;}
在读取obj.x for temp1之后,编译器将重新读取temp2的obj.x – 不是因为锁的魔力 – 而是因为不确定lock()是否被修改为obj.您可以设置编译器标志来积极地优化(无别名等),因此不会重新读取x,但是一堆代码可能会开始失败.@H_403_3@
对于temp3,编译器(希望)不会重新读取obj.x.
如果由于某种原因,obj.x可能在temp2和temp3之间改变,那么您将使用volatile(并且您的锁定将被破坏/无用).@H_403_3@
最后,如果你的lock()/ unlock()函数以某种方式内联,也许编译器可以评估代码,看到obj.x没有被改变.但是我保证这里有两件事情之一:
– 内联代码最终会调用一些 *** 作系统级锁定功能(从而防止评估)或
– 您调用一些asm内存屏障指令(即包装在__InterlockedCompareExchange中的内联函数),您的编译器将会识别,从而避免重新排序.@H_403_3@
编辑:我忘了提到 – 对于pthreads的东西,一些编译器被标记为“POSIX兼容”,这意味着,除了别的以外,它们将会识别pthread_函数,而不会对它们进行不好的优化.即使C标准尚未提到线程,那些编译器(至少最低限度)也是这样.@H_403_3@
所以,简短的回答@H_403_3@
你不需要挥发性.@H_403_3@ 总结
以上是内存溢出为你收集整理的c – 互斥体的存在有助于摆脱挥发性关键词吗?全部内容,希望文章能够帮你解决c – 互斥体的存在有助于摆脱挥发性关键词吗?所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)