我们是正经的技术内推交流群 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成内容
lewis89
V2EX    程序员

我们是正经的技术内推交流群

  •  
  • &nbs; lewis89 2020-12-29 00:22:10 +08:00 4683 次点击
    这是一个创建于 1828 天前的主题,其中的信息可能已经有所发展或是发生改变。
    迫于今早新加入的一个小老弟的提问,https://club.perfma.com/question/2079981

    我又是 debug 又是反编译,总算是把那个问题给整明白了
    https://github.com/jonwinters/jmm-research

    另外关于 x64 的 lock 的语义,大家有兴趣上 Stack Overflow 看,
    中文区我 Google 了一下,基本没有人能写博客给整明白的。

    再次申明:我们是正经的技术内推交流群,希望有大佬加入讨论吹水,
    哪怕是偶尔指点一下研究方向,也是不胜感激。

    微信 ID: Y2hlbjExMjIwMDM3Cg==
    第 1 条附言    2020-12-29 16:24:34 +08:00
    d3UzMDEzNTY4MQo=
    第 2 条附言    2020-12-29 16:24:45 +08:00
    更新:d3UzMDEzNTY4MQo=
    52 条回复    2021-01-26 18:47:01 +08:00
    xlzy905
        1
    xlzy905  
       2020-12-29 11:32:37 +08:00
    频繁了
    lewis89
        2
    lewis89  
    OP
       2020-12-29 11:36:36 +08:00
    先 mark 一下,昨天一下子吸收了 100 多人
    xujihua
        3
    xujihua  
       2020-12-29 12:36:10 +08:00
    加不上了 拉一下可以嘛 微信 ID:bW9yYXRn
    sanwantian
        4
    sanwantian  
       2020-12-29 12:45:34 +08:00
    拉一下可以嘛 微信 ID:finalesanwantian
    lewis89
        5
    lewis89  
    OP
       2020-12-29 13:54:14 +08:00
    已拉
    x940727
        6
    x940727  
       2020-12-29 13:59:25 +08:00
    求拉 BASE64:WHU1NzIxMTcyMzU=
    banjueaz
        7
    banjueaz  
       2020-12-29 14:19:13 +08:00
    微信 ID:zb547856757 麻烦拉一下
    lewis89
        8
    lewis89  
    OP
       2020-12-29 14:30:17 +08:00
    6-7 已拉
    TheF00L
        9
    TheF00L  
       2020-12-29 14:49:50 +08:00
    昨天加就频繁了 微信 ID: dsdnnt 麻烦拉一下
    boblin
        10
    boblin  
       2020-12-29 15:52:43 +08:00
    前端可以么
    wdmm
        11
    wdmm  
       2020-12-29 16:06:11 +08:00
    求拉 Base64: endkMTE3ODQ2MTQ5MA==
    MrCard
        12
    MrCard  
       2020-12-29 16:09:46 +08:00
    求拉,微信号:TW96YXJrIA==
    lewis89
        13
    lewis89  
    OP
       2020-12-29 16:09:56 +08:00
    @wdmm #11 可以
    wr516516
        14
    wr516516  
       2020-12-29 16:12:46 +08:00
    楼主还帮忙拉嘛 d3I1MTY1MTY=
    mosliu
        15
    mosliu  
       2020-12-29 16:13:56 +08:00
    VX 同 id 求拉
    hun2008hun
        16
    hun2008hun  
       2020-12-29 16:18:08 +08:00
    这代码有 bug 呀,可见性的反义词是不一定可见,以前也看到人拿这代码来纠结 system.out ,完全不能理解在想什么
    zhanbiqiyu
        17
    zhanbiqiyu  
       2020-12-29 16:20:50 +08:00
    d3UzMDEzNTY4MQo=

    大家可以加我微信,我拉大佬们进群
    lewis89
        18
    lewis89  
    OP
       2020-12-29 16:24:19 +08:00
    @boblin #10 都可以,我可能也会求助一些前端知识
    toma77
        19
    toma77  
       2020-12-29 16:24:47 +08:00
    求啦 微信号:bHhzdW5iaW4=
    lewis89
        20
    lewis89  
    OP
       2020-12-29 16:33:00 +08:00
    @hun2008hun #16 你去反编译看看就知道了,我研究的本来就是为什么 DEMO1 会在那里死循环,从 GDB 反汇编来看 主线程就是读不到 num 的最新值,至于为什么这样 我也不清楚,但是后面的 lock 指令 确确实实有内存栅栏的作用
    lewis89
        21
    lewis89  
    OP
       2020-12-29 16:36:51 +08:00
    @hun2008hun #16 纠结 System.out ? System.out 本身在 JIT 下也是有一个 lock 指令生成的,刚好就是这个 lock 之类充当了内存栅栏
    lewis89
        22
    lewis89  
    OP
       2020-12-29 16:37:46 +08:00
    Cowhitewhite
        23
    Cowhitewhite  
       2020-12-29 16:38:05 +08:00
    求拉:Y293aGl0ZXdoaXRl
    cnzjl
        24
    cnzjl  
       2020-12-29 16:52:21 +08:00
    求拉 R2xhZE1vbnN0ZXI=
    hun2008hun
        25
    hun2008hun  
       2020-12-29 17:13:30 +08:00
    @lewis89 因为 demo1 有 bug,而且严谨说不一定死循环,只是你的 cpu 是这样。 第二个问题:lock 的话要不把 sleep(1000)去掉再跑下?
    lewis89
        26
    lewis89  
    OP
       2020-12-29 17:30:20 +08:00
    @hun2008hun #25 我管它有没有 bug? 只要是代码 确实有人会这么想 也这么犯傻用过,我就去查问题出在哪里就好了,我 JDK8 在树莓派上就没这个事情,你去掉 sleep(1000)又要为什么,它这个本来就是要循环去读,主线程循环 10 秒钟后还是读不到最新的值,那又是为什么。
    只有用 lock 才能读到,lock 本身就是有内存栅栏的特性,我早就知道这个特性,这个东西只是验证 告诉你怎么一回事。
    lewis89
        27
    lewis89  
    OP
       2020-12-29 17:31:32 +08:00
    @hun2008hun #25 而且我在很多库的代码里面都看到有人用 volatile 去做可见性的同步,但同时并未使用 happen-before 语义
    junziyangyang
        28
    junziyangyang  
       2020-12-29 18:18:21 +08:00 via iPhone
    求拉 feng-junzi
    HAluelue
        29
    HAluelue  
       2020-12-30 09:08:33 +08:00
    求拉 andyis1iin
    GunsRose
        30
    GunsRose  
       2020-12-30 09:16:38 +08:00
    求拉 songtao22
    will2zuo
        31
    will2zuo  
       2020-12-30 10:12:34 +08:00
    求拉 zz546398578
    young1lin
        32
    young1lin  
       2020-12-30 13:54:35 +08:00
    使用 System.out 会导致锁粗化的。。。你可以看看极客时间的专栏《 Java 并发编程实战》有一章的评论里面就说过,我记得是日志打印的那一章。
    lewis89
        33
    lewis89  
    OP
       2020-12-30 13:57:51 +08:00
    @young1lin #32 这个问题跟锁粗化没有关系,而是 lock 的语义 有内存栅栏的作用
    young1lin
        34
    young1lin  
       2020-12-30 16:00:58 +08:00
    @lewis89 我看错了,我是,我就看到那个 monitorexit 了
    lewis89
        35
    lewis89  
    OP
       2020-12-30 16:24:55 +08:00
    @young1lin #34 monitorexit 下面的实现比较复杂 每个平台都不一样
    ezksdo
        36
    ezksdo  
       2021-01-23 14:40:33 +08:00
    原文里就有答案,能扯这么多。有 lock 就全局可见了?都锁的不是一个位置。
    lewis89
        37
    lewis89  
    OP
       2021-01-23 14:53:46 +08:00
    @ezksdo #36 哈,你不想研究就算了,不要瞎批评,我还真就告诉你 X86 有 lock 就能保障可见性 好吗? 跟锁不锁一个位置没有任何关系
    lewis89
        38
    lewis89  
    OP
       2021-01-23 14:55:34 +08:00
    @ezksdo #36 相同的语义 还有 mfence 会强制其它 CPU 刷写 write buffer
    lewis89
        39
    lewis89  
    OP
       2021-01-23 15:03:17 +08:00
    @ezksdo #36 请问 mfence MESI TSO NUMA 你了解几个? 你了解过了 再来批评也不迟
    ezksdo
        40
    ezksdo  
       2021-01-23 15:55:07 +08:00 via iPhone
    推荐你用 jitwatch 吧,看你 gdb 用得也费劲。这里就是 jit 优化,而打印函数有副作用,没有优化
    ezksdo
        41
    ezksdo  
       2021-01-23 15:56:39 +08:00 via iPhone
    你也不想想,不加 volatile 他就永远不写回内存吗?
    lewis89
        42
    lewis89  
    OP
       2021-01-23 16:05:15 +08:00
    @ezksdo #41 我不知道 JVM 为什么会有这种优化,jitwatch 又不能 debug,我在 gdb 里面 已经看过了,那个内存地址读出来的值就是 0 ,无论多久都是 0,至于是主线程 读到的是未失效的 L1/L2 cache,还是什么,我就不在乎了
    lewis89
        43
    lewis89  
    OP
       2021-01-23 16:16:27 +08:00
    @ezksdo #41

    https://www.zhihu.com/question/263528143/answer/270308453

    而且你从这个原答案里面可以看到
    lock addl $0x0, (%rsp); 对 rsp 指针 + 0 操作是毫无意义的,rsp 是栈顶指针
    lock 是让 cache 失效,保证可见性,如果可见性没有保证,代码依旧会死循环

    而对 变量 i 加 volatile 属性 并没有使用 happen before
    lewis89
        44
    lewis89  
    OP
       2021-01-23 16:25:46 +08:00
    @ezksdo #41 关键是我那个死循环的地方 你有留意看了没有,跟激进编译半毛钱关系都没有



    第一步要通过 R15 寄存器 偏移 0x108 的位置去取值,

    第二步才是跟存放了 立即值 0 的 RAX 寄存器比较

    比较失败跳回第一步 ,这跟 JVM 激进优化有半毛钱关系? 分明就是 [R15 + 0x108] 寄存器的指针 取不到新的值
    ezksdo
        45
    ezksdo  
       2021-01-23 16:28:03 +08:00 via iPhone
    cache 以行为单位,打印函数有 lock 并不能导致 num 变量可见,写 volatile 就是 happens before volatile 读的,我不知道你说的使用是什么
    lewis89
        46
    lewis89  
    OP
       2021-01-23 16:35:51 +08:00
    @ezksdo #45 如果读写 volatie.. 都是在同一个线程里面, 又何来一个线程 对 另外一个线程 观测到的 happen before ?
    lewis89
        47
    lewis89  
    OP
       2021-01-23 16:38:06 +08:00
    @ezksdo #45 你要 A 线程 写了 volatile,另外一个 B 线程 后续去读 volatile,保障 B 线程能观测到 A 线程写 volatile 的事情都发生,这才算是 happen before
    lewis89
        48
    lewis89  
    OP
       2021-01-23 16:38:48 +08:00
    你要 A 线程 写了 volatile,另外一个 B 线程 后续去读 volatile,保障 B 线程能观测到 A 线程写 volatile 之前的事情都发生,这才算是 happen before
    lewis89
        49
    lewis89  
    OP
       2021-01-23 16:39:11 +08:00
    @ezksdo #45
    你要 A 线程 写了 volatile,另外一个 B 线程 后续去读 volatile,保障 B 线程能观测到 A 线程写 volatile 之前的事情都发生,这才算是 happen before
    lewis89
        50
    lewis89  
    OP
       2021-01-26 18:37:36 +08:00
    @ezksdo #45 我错了,我重新静态分析了一下,没错是 激进编译的问题

    lewis89
        51
    lewis89  
    OP
       2021-01-26 18:39:45 +08:00
    @ezksdo #45 这几天在读 JVM 的操作数栈,忽然明白了这块,字节码所有的操作方法没有立即数,是使用操作数栈 来完成的,然后重新静态分析了一下,确实是 JVM 激进编译的锅
    lewis89
        52
    lewis89  
    OP
       2021-01-26 18:47:01 +08:00
    @ezksdo #45 人外有人,山外有山,老哥有兴趣加个好友,相互交流一下吗
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1232 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 32ms UTC 17:29 PVG 01:29 LAX 09:29 JFK 12:29
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86