java吧 关注:1,290,842贴子:12,821,639
  • 27回复贴,共1

菜鸟刚学JMM不久,有一个关于volatile修饰符的疑问,问问大家

只看楼主收藏回复

看的是jvm典中典《深入理解Java虚拟机》。说的volatile能保证可见性,但不能保证原子性。可见性我能理解,被volatile修饰的变量一旦在其中一个工作内存中被修改,那么其他工作空间对应的变量就失效了,当其他线程想使用这个变量却发现其已经失效后就会重新到主内存里去读取。
但我无法理解为啥不能保证原子性:现在主内存有变量i初始值为0,有2个线程A,B去调用它都想分别i++,假设线程A读取到i后,暂时搁置了,线程B读取到i后,将i值加1,再写回主内存,那么等A回过神来时,书上说的是A会将它原本读到的i加1然后写回主内存,这样主内存里i最终结果就为1而不是2,没能保证原子性。我想问的是当B修改i之后,A不应该发现自己工作空间的i已经失效了吗,A为什么不重新读取主内存已经被B修改过的i然后再进行i++,反而要固执地用最初的i值去i++?


IP属地:四川1楼2021-12-24 08:07回复
    帮帮菜鸟吧,大佬们😭😭


    IP属地:四川来自Android客户端2楼2021-12-24 08:09
    回复
      2025-12-11 21:35:09
      广告
      不感兴趣
      开通SVIP免广告
      文字有点多,对不住大家了,耐心看完吧求求了


      IP属地:四川来自Android客户端3楼2021-12-24 08:11
      回复
        我自己有一个猜测,不知道对不对,cpu只能在“读取”缓存中的变量时才能发现缓存行是否失效。而在对已经读取后拿到的变量进行加法减法啥的之前是不会去检查是否失效的😭😭这是我猜的我觉得好勉强啊


        IP属地:四川来自Android客户端4楼2021-12-24 08:15
        回复
          看看字节码指令,i++操作是多条指令完成的,在多线程环境下,如果不加锁,这多条指令不是原子的,自然无法保证原子性


          IP属地:四川来自Android客户端5楼2021-12-24 08:46
          回复
            j=i+1,如果已经赋值完,你i是最新的,但是j不一定是。这就为什么不能原子性。


            IP属地:福建来自Android客户端7楼2021-12-24 09:06
            收起回复
              我的理解是,++操作是由几个指令来完成的,到某个指令的时候就不在同步主内存的数据了


              IP属地:四川来自Android客户端8楼2021-12-24 09:13
              收起回复
                因为i++这行代码不能保证原子性, B执行完,a在执行++时,发现失效,重新读取,两个线程此时执行了两次++操作,而i改变了一次


                IP属地:陕西来自iPhone客户端10楼2021-12-24 09:21
                回复
                  2025-12-11 21:29:09
                  广告
                  不感兴趣
                  开通SVIP免广告
                  i++你可以理解分为3个操做,取i的值,i值加1,给i赋值。如果a线程执行i++,读取到了i为1,还没执行第二步b就读了i也为1。这是a执行完为1,b执行完了也为1。


                  IP属地:陕西来自Android客户端11楼2021-12-24 09:42
                  回复
                    violate是带有内存屏障的,只有它读的时候才会去主存读,已经读过的即使别的线程修改他也不知道,除非再读一次。


                    IP属地:陕西来自Android客户端12楼2021-12-24 09:44
                    收起回复
                      谢谢大家楼主已经懂了,大家真的太热心了


                      IP属地:四川来自Android客户端14楼2021-12-24 09:53
                      回复
                        真要说底层你可以看看JVM并发内存模型


                        IP属地:上海15楼2021-12-24 09:56
                        收起回复


                          IP属地:广东16楼2021-12-24 11:09
                          回复
                            volatile 的原子性是指对字节操作的原子性 如一个long要读2次 这2次是原子的


                            IP属地:浙江17楼2021-12-24 13:42
                            回复
                              2025-12-11 21:23:09
                              广告
                              不感兴趣
                              开通SVIP免广告
                              i++是先读后写 不能保证两个操作的原子性。


                              IP属地:广东来自Android客户端18楼2021-12-24 14:11
                              回复