现在的位置: 首页 > 综合 > 正文

c++和java中的atomic/volatile

2013年12月17日 ⁄ 综合 ⁄ 共 1037字 ⁄ 字号 评论关闭

看到两篇不错的文章,分别介绍atomic和olatile关键字在java和c++中的表现,很不错。

long count = 0;
for(int i=0; i<1000; i++)
    count++;

这段代码在c++中,经过编译后,count会被优化到寄存器中,++的操作也都是针对寄存器的;如果加上volatile关键字,可以保证count不会被优化到寄存器,每次都走内存;如果使用atomic<long>,除了像volatile会走内存外,还会在add指令前,加上lock前缀。

这里所有的内存只是虚指,可能在cpu cache中,cpu cache之间的同步由内存硬件保证。

http://brooker.co.za/blog/2012/11/13/increment.html

http://brooker.co.za/blog/2013/01/06/volatile.html

intel的手册对lock前缀的说明如下:

  1. 确保对内存的读-改-写操作原子执行。在Pentium及Pentium之前的处理器中,带有lock前缀的指令在执行期间会锁住总线,使得其他处理器暂时无法通过总线访问内存。很显然,这会带来昂贵的开销。从Pentium 4,Intel Xeon及P6处理器开始,intel在原有总线锁的基础上做了一个很有意义的优化:如果要访问的内存区域(area of memory)在lock前缀指令执行期间已经在处理器内部的缓存中被锁定(即包含该内存区域的缓存行当前处于独占或以修改状态),并且该内存区域被完全包含在单个缓存行(cache
    line)中,那么处理器将直接执行该指令。由于在指令执行期间该缓存行会一直被锁定,其它处理器无法读/写该指令要访问的内存区域,因此能保证指令执行的原子性。这个操作过程叫做缓存锁定(cache locking),缓存锁定将大大降低lock前缀指令的执行开销,但是当多处理器之间的竞争程度很高或者指令访问的内存地址未对齐时,仍然会锁住总线。
  2. 禁止该指令与之前和之后的读和写指令重排序。
  3. 把写缓冲区中的所有数据刷新到内存中。

http://stackoverflow.com/questions/7346893/out-of-order-execution-and-memory-fences

http://stackoverflow.com/questions/558848/can-i-force-cache-coherency-on-a-multicore-x86-cpu

抱歉!评论已关闭.