java吧 关注:1,248,522贴子:12,730,858
  • 11回复贴,共1

关于java的Volatile

只看楼主收藏回复


学习单例模式时候了解到volatile能禁止指令重排(对于new Object()的具体指令:分配内存空间,设置地址,对象初始化),接着搜索了解到java代码执行顺序也能被重排(也算是指令重排?),比如这里的ready没有被volatile修饰,理论上count是有可能大于0的,但是我多次执行代码count都没有大于0,是因为"java代码执行顺序也能被重排"是错的吗,如果不是如何能让这种错误出现的机会更大?


IP属地:广东1楼2024-01-16 02:31回复
    java指令这个应该是没有指令重排的。jvm应该是不会实现这个的。
    我搜jvm规范里面,这个关键字介绍很短,就是说了这个关键字是刷新缓存。


    IP属地:湖南来自Android客户端2楼2024-01-16 07:38
    收起回复
      这说的太简单了,可见性我理解,比如说改了以后立马刷新所有的CPU缓存。强制它们重新从内存取。
      但是这个和指令重排序有啥关系呢?


      IP属地:湖南来自Android客户端3楼2024-01-16 07:58
      回复
        JVM里面也只是标注,不能够被缓存。


        IP属地:湖南来自Android客户端4楼2024-01-16 08:02
        回复
          应该就这样了,内存屏障就会禁止指令重排序。最重要的原因是jvm的指令并不都是原子操作的。


          IP属地:湖南来自Android客户端6楼2024-01-16 08:15
          收起回复
            你这个不是重排序的问题 你这个测试代码表现出来得是可见性问题 。下面几点
            1: 线程启动 != 线程执行 也就是 t1 和 t2 谁先执行不是决定得而是创造系统觉得 start() 并不会立马执行 它要受操作系统调度决定
            2:t1 和 t2 有可能不在一个CPU上执行(虽然这个几率不大) 那么对于 read 这个变量 所处于各自CPU的cacheLine 不会被保证同步 也就是如果t1 在CPU 1 上执行 read = true t2 在CPU2 上的 read 所在的cacheline 不会被通知作废 自然也不会被更新 JMM不保证
            3: java代码执行顺序也能被重排 这句话是不对的 通常是指令排序。这个代码可能被编译器优化了(大概率) 需求看汇编 。
            4: 两个线程执行代码 t1 ,t2 他们共享一个变量 这里read 或者 他们存在先后关系 指令也可能被重排序。


            IP属地:湖北8楼2024-01-16 13:36
            收起回复
              你要明白volatile 是一种规范 是JAVA 对单个原子操作(指令级别的)的线程安全保证。 volatile的怎么保证的,细节就和 CPU 指令架构, Cpu CacheLine ,并发协议(例如mesi) ,内存屏障有关系。你只需要知道 并发问题是有个先后顺序的 。通常重排序导致的并发问题是非常隐秘。大多是可见性问题 和原子操作问题。
              例如:
              1: 两个线程 t1,t2 同享一个变量 a 。如果这两个线程执行不在一个CPU上。 那么 t1 改变a ,t2是不会被保证立马知道 甚至都不会被保证知道。
              2: 如果t1,t2 是同一个CPU 那么就会出现原子操作问题 也就是 你的store操作 也就是read = true 是 多指令操作 而load 操作是单指令 。注意CPU执行架构是流水线式的 也就是一个操作会被分割成多个子命令 同类型的子命令(不存在依赖关系) 会一起执行 尽量减少CPU流水线暂停。
              3: 才是重排序问题。也就是重排序只会的指令会 使CPU流水线更高效。
              更细节的东西 你需求去掌握操作系统设计


              IP属地:湖北12楼2024-01-17 13:50
              回复



                IP属地:湖北13楼2024-01-17 13:59
                回复
                  谢谢绑架邻居的黑猫的回答,太厉害了


                  IP属地:广东14楼2024-01-17 14:35
                  回复