V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
lewis89
V2EX  ›  程序员

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

  •  
  •   lewis89 · Dec 29, 2020 · 4850 views
    This topic created in 1948 days ago, the information mentioned may be changed or developed.
    迫于今早新加入的一个小老弟的提问,https://club.perfma.com/question/2079981

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

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

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

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

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



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

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

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

    lewis89
        51
    lewis89  
    OP
       Jan 26, 2021
    @ezksdo #45 这几天在读 JVM 的操作数栈,忽然明白了这块,字节码所有的操作方法没有立即数,是使用操作数栈 来完成的,然后重新静态分析了一下,确实是 JVM 激进编译的锅
    lewis89
        52
    lewis89  
    OP
       Jan 26, 2021
    @ezksdo #45 人外有人,山外有山,老哥有兴趣加个好友,相互交流一下吗
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   4587 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 125ms · UTC 04:01 · PVG 12:01 · LAX 21:01 · JFK 00:01
    ♥ Do have faith in what you're doing.