当前位置:  开发笔记 > 大数据 > 正文

使用C/Pthreads:共享变量需要是不稳定的吗?

如何解决《使用C/Pthreads:共享变量需要是不稳定的吗?》经验,为你挑选了3个好方法。

在C编程语言中,Pthreads作为线程库; 在线程之间共享的变量/结构是否需要声明为volatile?假设他们可能受到锁定或不受保护(可能是障碍).

pthread POSIX标准对此有任何发言权,是依赖于编译器还是不依赖于编译器?

编辑添加:感谢您的回答.但是,如果你使用锁,那该怎么办?如果你使用障碍物怎么办?或者使用比较和交换等原语直接和原子地修改共享变量的代码......



1> Don Neufeld..:

只要您使用锁来控制对变量的访问,就不需要使用volatile.事实上,如果你在任何变量上放置volatile,你可能已经错了.

https://software.intel.com/en-us/blogs/2007/11/30/volatile-almost-useless-for-multi-threaded-programming/


如果您不使用锁,几乎肯定需要使用显式内存屏障.请注意,volatile不是内存屏障,因为它不会影响除volatile变量本身之外的任何其他加载和存储.这通常也是一种悲观情绪.
这个答案是错误的。这篇文章是错误的。本文底部的注释说明了原因。本文的作者完全误解了volatile的目的。阅读其他答案以了解_actually_的含义。

2> 小智..:

答案是绝对的,毫不含糊的,不.除了正确的同步原语之外,您不需要使用'volatile'.需要完成的一切都是由这些原语完成的.

使用'volatile'既不必要也不充分.没有必要,因为适当的同步原语就足够了.这是不够的,因为它只会禁用一些优化,而不是所有可能会咬你的优化.例如,它不保证另一个CPU的原子性或可见性.

但除非你使用volatile,否则编译器可以自由地将共享数据缓存在寄存器中任何时间长度...如果你希望你的数据被写入可预测地写入实际内存而不是仅仅缓存在寄存器中编译器自行决定,您需要将其标记为volatile.或者,如果您在离开修改它的函数后才访问共享数据,那么您可能没问题.但我建议不要依赖盲目的运气来确保将值从寄存器写回到内存中.

是的,但即使您使用volatile,CPU也可以将共享数据缓存在写入发布缓冲区中任意长度.可以咬你的优化集与'volatile'禁用的优化集不完全相同.因此,如果你使用'volatile',你就是依靠盲目的运气.

另一方面,如果您使用具有已定义的多线程语义的sychronization原语,则可以保证事情能够正常工作.作为一个优点,你不会受到'volatile'的巨大打击.那么为什么不这样做呢?



3> jakobengblom..:

我认为volatile的一个非常重要的属性是它在变量时将变量写入内存,并在每次访问时从内存重新读取.这里的其他答案混合了volatile和同步,从其他一些答案可以清楚地看出,volatile不是同步原语(信用到期的信用).

但除非你使用volatile,否则编译器可以自由地将共享数据缓存在寄存器中任何时间长度...如果你希望你的数据被写入可预测地写入实际内存而不是仅仅缓存在寄存器中编译器自行决定,您需要将其标记为volatile.或者,如果您在离开修改它的函数后才访问共享数据,那么您可能没问题.但我建议不要依赖盲目的运气来确保将值从寄存器写回到内存中.

特别是在富寄存器的机器上(即不是x86),变量可以在寄存器中存活很长时间,而良好的编译器甚至可以缓存寄存器中的部分结构或整个结构.所以你应该使用volatile,但是为了性能,还要将值复制到局部变量进行计算,然后进行显式回写.从本质上讲,有效地使用volatile意味着在C代码中进行一些加载存储思维.

在任何情况下,您都必须使用某种操作系统级别提供的同步机制来创建正确的程序.

有关volatile的弱点的一个例子,请参阅我在http://jakob.engbloms.se/archives/65上的 Decker算法示例,这证明了volatile不能同步.


将变量长期保存在寄存器中正是编译器优化器的重点.使用volatile完全否定了这一点.注意,在GCC(可能是大多数编译器)函数调用clobber内存,这意味着如果你写一个非局部变量然后做一个函数调用,编译器不允许在函数调用后推送写入 - 这似乎是什么无论如何你的意图是使用volatile.这不是什么挥发性的...
几乎没有关于这个答案是正确的.特别是,`volatile`不会强制数据被预测地写入实际内存,标准中没有任何内容需要它.同样,它不会*在大多数现代机器上执行此操作,而且标准不要求它.
易失性用于标记可以自发改变的变量(嵌入式系统将硬件实体映射到存储器位置就是这种情况的一个例子).如果使用独占锁定,普通变量不能自发变化.Herb Sutter的文章相当不错:http://www.ddj.com/hpc-high-performance-computing/212701484
推荐阅读
低调pasta_730
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有