C ++读取和写入一个intprimefaces?
我有两个线程,一个更新int和一个读取它。 这是一个统计值,读写的顺序是不相关的。
我的问题是,我是否需要同步访问这个多字节值呢? 换句话说,可以将部分写入完成并中断,然后再进行读取。
例如,将值= 0x0000FFFF的值设为0x00010000。
有没有什么值得看的我应该担心的0x0001FFFF? 当然,types越大,发生这种事情的可能性就越大。
我总是同步这些types的访问,但很好奇社区的想法。
起初,人们可能会认为读取和写入本地机器大小是primefaces性的,但是还有许多问题需要处理,包括处理器/内核之间的高速caching一致性。 在Windows上使用像Interlocked *这样的primefaces操作,在Linux上也是这样。 C ++ 0x将有一个“primefaces”模板来包装这些在一个很好的和跨平台的界面。 现在,如果您正在使用平台抽象层,它可能会提供这些function。 ACE所做的,请参阅类模板ACE_Atomic_Op 。
男孩,什么问题。 答案是:
是的,不,呃,那要看情况
这一切都归结为系统的体系结构。 在IA32上,一个正确alignment的地址将是一个primefaces操作。 未alignment的写入可能是primefaces的,这取决于正在使用的caching系统。 如果内存位于一个单一的L1caching线内,那么它是primefaces的,否则不是。 CPU和RAM之间的总线宽度会影响primefaces性质:在8086上正确alignment的16位写是primefaces的,而在8088上的相同写不是因为8088只有8位总线,而8086有16位总线。
另外,如果您使用的是C / C ++,不要忘记将共享值标记为volatile,否则优化器会认为variables永远不会在您的某个线程中更新。
如果您正在读取/写入4字节的值并且它在内存中是双字节alignment的,而您正在I32架构上运行,那么读取和写入是primefaces的。
是的,你需要同步访问。 在C ++ 0x中它将是一个数据竞争和未定义的行为。 POSIX线程已经是未定义的行为。
在实践中,如果数据types大于本地字大小,可能会得到错误的值。 此外,由于优化移动读取和/或写入,另一个线程可能永远不会看到写入的值。
你必须同步,但是在某些体系结构中,有效的方法来实现它。
最好是使用子例程(可能在macros后面隐藏),以便可以有条件地将实现replace为特定于平台的实现。
Linux内核已经有一些这样的代码。
在Windows上,联锁***交换***添加保证是primefaces的。
为了回应大家在楼上所说的话,C ++ 0x之前的语言不能保证从multithreading访问共享内存的任何事情。 任何保证将由编译器决定。
不,他们不是(或者至less你不能假设他们是)。 话虽如此,有一些技巧可以做到这一点,但它们通常不可移植(请参阅比较和交换 )。
我同意许多人,尤其是杰森 。 在Windows上,可能会使用InterlockedAdd及其朋友。
从上面提到的caching问题…
如果你把代码移植到一个寄存器尺寸较小的处理器上,它就不再是primefaces了。
国际海事组织,线程问题太棘手,不敢冒险。
让我们来看看这个例子
int x; x++; x=x+5;
第一个语句被假定为primefaces的,因为它转化为一个单一的CPU周期的INC汇编指令。 但是,第二个任务需要几个操作,所以显然不是一个primefaces操作。
另一个例如,
x=5;
再次,你必须反汇编代码,看看到底发生了什么。
TC,我认为你使用常数(如6)的那一刻,指令不会在一个机器周期内完成。 尝试查看与x ++相比x + = 6的指令集
有人认为++ c是primefaces的,但是要注意生成的程序集。 例如'gcc -S':
movl cpt.1586(%rip), %eax addl $1, %eax movl %eax, cpt.1586(%rip)
要增加一个int,编译器首先将它加载到一个寄存器中,并将其存回内存。 这不是primefaces的。
肯定不! 来自我们最高C ++权威人士M. Boost的回答:
对“普通”variables的操作不能保证是primefaces的。
唯一可移植的方法是使用signal.h头文件中为您的编译器定义的sig_atomic_ttypes。 在大多数C和C ++实现中,这是一个int。 然后声明你的variables为“volatile sig_atomic_t”。