美文网首页java进阶干货程序员
如何保证数组元素的可见性

如何保证数组元素的可见性

作者: 美团Java | 来源:发表于2018-03-22 15:00 被阅读1415次

问题

之前有小伙伴在星球提了这么一个问题

这篇文章时隔一两年,突然看到还是有点印象,文章中,我只是强硬的抛出了一个结论:虽然table变量被volatile修饰了,但里面的元素并没有volatile修饰,无法保证元素的可见性。

但是这种解释,似乎被众多的小伙伴怀疑,也一直没有找到有理的证据(基础还是太弱)

不过在星球中,大家还是很积极的讨论,虽然有些是错的(这种问题在大部分人身上都有,你不表现出来,那你永远不知道自己所掌握的东西其实是不对的)

解惑

在ConcurrentHashMap(1.8)中,内部使用一个volatile的数组table保存数据,细心的同学可以发现,Doug Lea每次在获取数组的元素时,采用Unsafe类的getObjectVolatile方法,在设置数组元素时,采用compareAndSwapObject方法,而不是直接通过下标去操作,这是为什么?

今天得到R大的确认:这个是因为Java数组在元素层面的元数据设计上的缺失,无法表达元素是final、volatile等语义,所以开了后门,使用getObjectVolatile用来补上无法表达元素是volatile的坑,@Stable用来补上final的坑,数组元素就跟没有标volatile的成员字段一样,无法保证线程之间可见性。

只有触发happens before关系的操作,才能保证线程之间的可见性,比如使用table[0] = new Object()直接赋值,这个赋值不会触发任何happens before关系的操作,相当于对一个无volatile变量进行赋值一样。

加入知识星球,不仅可以查漏补缺,还可以验证自己对Java的理解。
目前已有260+小伙伴加入。

相关文章

  • JITWatch

    问题1:volatile 修饰数组时能否保证数组元素的可见性? vo...

  • 如何保证数组元素的可见性

    问题 之前有小伙伴在星球提了这么一个问题 这篇文章时隔一两年,突然看到还是有点印象,文章中,我只是强硬的抛出了一个...

  • volatile

    目标 1、volatile如何保证内存可见性2、volatile如何禁止指令重排序3、内存屏障4、内存可见性5、关...

  • Majority Element

    问题: 给定一个n元素数组,求出现次数最大的元素(即Majority Element),并且数组保证该元素出现的次...

  • JavaScript基础—数组

    数组基础 创建一个空数组: 数组里的元素可以是任意类型: 通过索引获取数组元素: 如何遍历数组: 如何获取数组长度...

  • Sychronized & Volatile

    Synchronized 保证了可见性 ,并且保证了原子性Volatile只保证了可见性,不能保证原子性,即只能保...

  • 死磕 java同步系列之volatile解析

    问题 (1)volatile是如何保证可见性的? (2)volatile是如何禁止重排序的? (3)volatil...

  • 并发编程-synchronized关键字大总结

    0、synchronized 的特点: 可以保证代码的原子性和可见性。 1、synchronized 的性质: 可...

  • Go基础系列:7. 内置集合 - 数组

    学到什么 什么是数组? 如何获取数组长度? 如何操作数组元素? 如何比较两个数组? 如何拷贝数组? 如何创建多维数...

  • JS数组

    如何创建数组,数组元素的读和写数组元素的的length属性 第二种创建数组元素的读写读取和设置时,使用方括号[],...

网友评论

  • bc3425b60480:楼主测试过吗?
    测试之后数组元素是volatile的
    是我的测试方法有问题吗?
    public class work2 {
    public static void main(String[] args)
    {
    try
    {
    Test t = new Test();
    t.start();
    Thread.sleep(2000);
    t.setRunning(false);
    System.out.println("已赋值为false");
    }
    catch (InterruptedException e)
    {
    e.printStackTrace();
    }
    }
    }
    class Test extends Thread
    {
    private volatile boolean[] isRunning = new boolean[10];

    public Test(){
    isRunning[0]=true;
    }

    public void setRunning(boolean isRunning)
    {
    this.isRunning[0]=isRunning;

    }

    public void run()
    {
    System.out.println("进入run了");
    while (isRunning[0]== true){};
    System.out.println("线程被停止了");
    }
    }
  • 刘志磊LJ:您好,对于您上面的解惑,我是不是可以认为对于concurrenthashmap,每个线程都能获取到最新的table元素呢:joy:
  • 刘志磊LJ:“数组元素就跟没有标volatile的成员字段一样,无法保证线程之间可见性”
    引用这句话,请问一下如果是copyonwritearrayist,也不能保证每次get都是最新的元素吗,即便数组也同样被volatile修饰
  • 4eadb3ef44df:getObjectVolatile强制每次都拿到最新的值,compareAndSwapObject使用无锁进行修改操作,分别对应锁的可见性和原子性语意
  • 0701fa97be25:我理解的是数组在java中是一个特殊的对象,对象引用设置volatile,并不能保证内部元素的volatile语义(内存可见性,更新缓存会使得其他CPU核的缓存行失效)。所以只能通过Unsafe.putObjectVolatile来保证设置对象的volatile语义。
  • HoldGone:r大是谁呢😊
    MinamiSun:RednaxelaFX,做jvm开发的人,技术很厉害。
    西瓜摊子:R大都没听过?

本文标题:如何保证数组元素的可见性

本文链接:https://www.haomeiwen.com/subject/khsvqftx.html