java吧 关注:1,291,301贴子:12,819,790

回复:兄弟们继上次的指令重排后我又发现一个超级狠活

只看楼主收藏回复

cpu不一定实现了mesi


IP属地:四川来自Android客户端17楼2025-02-04 10:21
回复
    内存屏障防了重排序 还有storebuffer和invalidqueue可能mesi不生效


    IP属地:四川来自Android客户端18楼2025-02-04 10:27
    回复
      2025-12-15 03:27:47
      广告
      不感兴趣
      开通SVIP免广告
      有ai工具不用瞎想什么


      IP属地:广东来自Android客户端19楼2025-02-04 13:05
      回复
        层级不一样 mesi是cpu硬件级别 volatile是应用级别


        IP属地:陕西来自Android客户端20楼2025-02-04 13:35
        回复
          层级不一样,jvm有自己的内存模型,线程会有自己工作内存的共享变量副本,volatile要使它失效。需要注意Java是面向jvm的


          IP属地:湖南来自Android客户端21楼2025-02-04 16:53
          回复
            你应该庆幸活在一个背八股文就能有工作不被淘汰的好时代


            IP属地:日本来自iPhone客户端22楼2025-02-05 03:37
            收起回复
              你要知道java内存模型中每个线程都有自己的工作内存,这个工作内存包括CPU寄存器、L1缓存。首先volatile关键字有两种作用,第一种是保证可见性、第二种是禁止指令重排序。我们先说第一种保证可见性:又分为volatile读和volatile写,在hotspotVM实现中,volatile读使用的是C语言中的volatile关键字(想深入了解的话可以去看hotspot源码中的byteInterpreter.cpp文件),c语言中的volatile关键字就是告诉编译器不要对该关键字修饰的变量进行优化(也就是不要缓存在寄存中,每次都从内存中取最新的值)。而volatile写:则是使用了lock指令:该指令是对缓存行加锁,从而同一时刻只有一个线程可以访问该变量,而且会立即将最新值刷入内存,从而保证了volatile变量写入内存这个行为的原子性和可见性。注意这里只是保证了写入内存这个过程的原子性。至于你说的MESI,这是intel cpu产品下的缓存一致性协议,它只针对缓存行,本质上是各个cpu核心通过总线进行交流,使其它核心的L1?L2缓存中的缓存行失效。假设这里有一个没有volatile修饰的变量a、有两个线程同时对该变量执行a++操作,这种情况就是你说的仅有mesi的情况:线程A的代码由CPU核心A执行,线程B的代码由CPU核心B执行,首先核心A先将变量a加载到L1缓存的缓存行中,此时该缓存行的状态为E,表示由A独占,然后A将混存行中a变量的值加载到寄存器中准备执行+1操作,这个时候核心A收到核心B的消息:请求将a的值共享给B核心,随后A核心通过总线将a共享给B核心,此时两个核心的缓存行状态都变为S,这个时候B核心要修改a变量的值,就发送失效消息给A核心,但是A核心已经将a的值加载到寄存器中了,失效与否都没有用了,因为mesi作用于缓存行,对于已经加载到寄存器中的值毫无卵用。所以AB两个核心的值相同,都执行a++操作,最后得到的值也相同。如果使用了volatile变量,还是可能存在这个问题,因为volatile只保证了写入内存过程的原子性,对于已经加载到寄存器中的值也无能为力。所以要保证整个a++行为的原子性才能保证线程安全问题!


              IP属地:四川23楼2025-02-05 14:00
              回复