当前位置: 首页 > 知识库问答 >
问题:

volatile环境下JIT生成的x86输出分析

龚鸿羽
2023-03-14
public class Main {
    private int x;
    private volatile int g;


    public void actor1(){
       x = 1;
       g = 1;
    }


    public void actor2(){
       put_on_screen_without_sync(g);
       put_on_screen_without_sync(x);
    }
}
   .................(I removed not important body of method).....

  0x00007f42307d9d5e: c7460c01000000     (1) mov       dword ptr [rsi+0ch],1h
                                                ;*putfield x
                                                ; - package.Main::actor1@2 (line 14)

  0x00007f42307d9d65: bf01000000          (2) mov       edi,1h
  0x00007f42307d9d6a: 897e10              (3) mov       dword ptr [rsi+10h],edi
  0x00007f42307d9d6d: f083042400          (4) lock add  dword ptr [rsp],0h
                                                ;*putfield g
                                                ; - package.Main::actor1@7 (line 15)

  0x00007f42307d9d72: 4883c430            add       rsp,30h
  0x00007f42307d9d76: 5d                  pop       rbp
  0x00007f42307d9d77: 850583535116        test      dword ptr [7f4246cef100h],eax
                                                ;   {poll_return}
  0x00007f42307d9d7d: c3                  ret
 int tmp = i; // volatile load
 // [LoadStore]
 // [LoadLoad]
 // [StoreLoad] -- this one
 int tmp = i; // volatile load
 // [LoadStore]
 // [LoadLoad]

需要有一个连续的一致性

但是,我不明白为什么要有顺序的一致性。

共有1个答案

慕容雅珺
2023-03-14

首先,将被刷新到内存-这是非常错误的。它几乎从来没有冲过主内存--它通常会将StoreBuffer排空到L1,并且由缓存一致性协议来同步所有缓存之间的数据,但如果您更容易理解这个概念,那么它也很好--只需知道这一点略有不同且速度更快。

这是一个很好的问题,为什么[StoreLoad]会出现在那里,也许这会让事情变得更清楚一些。volatile实际上都是关于栅栏的,下面是一个示例,说明在执行某些volatile操作时会插入哪些屏障。例如,我们有一个volatile load:

  // i is some shared volatile field
  int tmp = i; // volatile load of "i"
  // [LoadLoad|LoadStore]

请注意LoadStoreLoadLoad中的两个障碍;简而言之,它意味着在volatile load/read之后的任何loadstore都不能“上移”屏障,它们不能在volatile load的“上方”重新排序。

 // "i" is a shared volatile variable
 // [StoreStore|LoadStore]
 i = tmp; // volatile store
 // any store of some other volatile
 // can not be reordered with this volatile load
 // [StoreLoad] -- this one
 int tmp = i; // volatile load of a shared variable "i"
 // [LoadStore|LoadLoad]
// [StoreStore|LoadStore]
i = tmp; // volatile store
// [StoreLoad] -- and this one

假设您有这样的情况:

[StoreStore|LoadStore]
int x = 4; // volatile store of a shared "x" variable

int y = 3; // non-volatile store of shared variable "y"

int z = x; // volatile load
[LoadLoad|LoadStore]

基本上不存在阻止volatile storevolatile load重新排序的障碍(即:首先执行volatile load),这显然会引起问题;从而违反顺序一致性。

顺便说一句(如果我没有搞错的话),通过在volatile load可见之前,不会对volatile load之后的每一个操作进行重新排序您有点错过了这一点。volatile本身不可能重新排序-其他操作可以自由重新排序。我给大家举个例子:

 int tmp = i; // volatile load of a shared variable "i"
 // [LoadStore|LoadLoad]

 int x = 3; // plain store
 int y = 4; // plain store
 int tmp = i; // volatile load
 // [LoadStore|LoadLoad]

 // see how they have been inverted here...
 int y = 4; // plain store
 int x = 3; // plain store
 类似资料:
  • 问题内容: 我写这篇文章与深入了解Java中的volatile有关 现在,我正在分析JIT为上面的代码生成的内容。从上一篇文章的讨论中,我们知道输出是不可能的,因为: 写挥发的原因,每一个动作前述原因,那之前是可见的(将被刷新到内存)将是可见的。 我是否正确理解它可以工作,因为x86无法重新排序?如果可以,则需要附加的内存屏障,是吗? 优秀@Eugene的答案后编辑: 在这里,我明白您的意思了-很

  • 如果你使用了 vux2 模板或者 webpack 模板,默认你可以直接通过判断 process.env.NODE_ENV 来区分 比如统计代码仅放在 production 环境,在不同环境里使用不同的 API 接口地址。 if (process.env.NODE_ENV === 'production') { // 干一些线上才要做的事情 } if (process.env.NODE_ENV

  • 标签(空格分隔): EBOOKCHAIN PM2 NODEJS [TOC] 前言 部署前请先安装Ebookcoin 请参考官方wiki:https://github.com/Ebookcoin/ebookcoin/wiki/ pm2简介 Node.js默认单进程运行,对于32位系统最高可以使用512MB内存,对于64位最高可以使用1GB内存。对于多核CPU的计算机来说,这样做效率很低,因为只有一个

  • 本文向大家介绍linux环境下java程序打包成简单的hello world输出jar包示例,包括了linux环境下java程序打包成简单的hello world输出jar包示例的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了linux环境下java程序打包成简单的hello world输出jar包。分享给大家供大家参考,具体如下: 1. linux必须已安装java环境,测试   说明j

  • 我目前正在学习多线程,我发现了一些我无法解释的有趣的东西。据我所知,如果两个线程访问一个静态变量,它们可以将自己的副本复制到缓存中。Thread1对其本地缓存中的静态变量进行的更新不会反映在Thread2缓存的静态变量中。 java java