Tho*_*son 14 c c# c++ java concurrent-programming
我在许多参考文献中发现它提到volatile在C/C++中很弱并且可能在多处理器的并发环境中引起问题,但它(volatile)可以用作C#/ Java中差异CPU之间的通信机制.看起来这个关键字在C#/ Java中比在C/C++中更严格,但它们之间的差异/影响是什么?
这是volatileC/C++ 的参考.
为什么volatile在多线程C或C++编程中不被认为有用?
Nad*_*_MK 13
对于C#/ Java," volatile"告诉编译器必须永远不要缓存变量的值,因为它的值可能会在程序本身的范围之外发生变化.然后,如果变量"在其控制范围之外",则编译器将避免可能导致问题的任何优化.
在C/C++中,volatile在开发嵌入式系统或设备驱动程序时需要" ",您需要读取或写入内存映射的硬件设备.特定设备寄存器的内容可能随时更改,因此您需要使用" volatile"关键字来确保编译器不会优化此类访问.
volatile关键字对语言及其实现的平台非常主观.虽然Java在所有体系结构中提供了一致的volatile性能,但直接编译到本机机器平台的语言并不是这种情况,例如在C/C++的情况下.让我们试着理解为什么会这样.
设a,b是一组程序动作P的成员,而v_ {n}(a)是将波动率要求应用于动作的函数,其中下标_n表示应用易失性动作的第_n次迭代和\ rightarrow是先前的运算符,如前所述.对于所有程序操作,以下规则成立:
v_n(a)\ rightarrow v_ {n + 1}(a)
a\rightarrow v_n(b)\ Rightarrow a\rightarrow v_ {n + i}(b)其中i\in\mathbb {N}
规则1表示所有易失性函数都强制执行总顺序,其中函数v_ {n}(a)总是在v_ {n + 1}(a)之前,其中规则2表示如果动作a在动作上的volatile函数之前b在第_n次迭代中,动作a必须先于应用于b的所有后续volatile函数.
这是Java中非常强大的内存需求,实际上它比C/C++强得多.C/C++语言规范对内存排序没有这样的限制,并将其留给编译器实现来决定如何围绕易失性动作排序非易失性动作.
让我们考虑这些规则如何通过简单的代码示例影响程序执行:
int a = 0;
int b = 0;
volatile int count = 0;
a = 1;
count = 1;
b = 2;
count = 2;
Run Code Online (Sandbox Code Playgroud)
在C/C++中,volatile关键字只保证count变量不能相互重新排序,即.如果count == 2,那么count = 1必须先于它.但是,既不保证a == 1,也不保证b == 2.
在Java中,给定上面定义的更强保证,那么如果count == 1,那么断言a == 1必须为真.类似地,如果count == 2,则断言a == 1 && b == 2必须为真.这就是Java提供的严格的内存保证意味着C/C++没有.
但是,这并不意味着C/C++的行为方式与Java不同.是否这样做取决于(1)编译器是否执行任何可能令人惊讶的顺序但是合法顺序的代码重新排序,以及(2)基础机器架构是否支持相同的严格内存顺序,前提是编译器不执行任何令人惊讶的代码重新排序.
例如,在所有x86平台上使用-O0设置的gcc上编译代码将符合(并且比Java内存模型更严格),但其他体系结构(如PowerPC,Alpha,Itanium)都支持较弱的内存模型,这可能会出现令人惊讶的程序程序员可能不会期望的行为.警告Lector!
无论如何,如果您对更多内存模型一致性规则感兴趣,您可能需要观看英特尔对x86内存模型的解释,其中详细解释了内存排序的细微差别.请享用!
在 C/C++ 中,volatile没有与多线程相关的特定语义,因此它在该上下文中的行为是特定于平台的。C# 和 Java 为volatile. 所以您知道自己会得到什么并且可以信赖它。
| 归档时间: |
|
| 查看次数: |
5340 次 |
| 最近记录: |