Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 垃圾收集和同步可见性_Java_Multithreading_Synchronized_Volatile - Fatal编程技术网

Java 垃圾收集和同步可见性

Java 垃圾收集和同步可见性,java,multithreading,synchronized,volatile,Java,Multithreading,Synchronized,Volatile,我读到过关于将对象标记为volatile并不能保证其成员的可见性的文章(我不是说线程安全,只是说内存可见性,引用: JVM只会认为对象引用是不稳定的,而不会认为对象数据本身是驻留在堆上的 我的问题是: 同步将确保成员(在同一个锁对象上)在被编辑的情况下的可见性。这是因为在锁结束(释放)之前发生的操作使其他线程可见吗 如果在对象上使用volatile,并且对象引用发生更改。如果旧引用缓存在一个线程CPU缓存中,会发生什么情况?GC会使其保持活动状态吗 示例代码: class Test{ vol

我读到过关于将对象标记为volatile并不能保证其成员的可见性的文章(我不是说线程安全,只是说内存可见性,引用:

JVM只会认为对象引用是不稳定的,而不会认为对象数据本身是驻留在堆上的

我的问题是:

  • 同步将确保成员(在同一个锁对象上)在被编辑的情况下的可见性。这是因为在锁结束(释放)之前发生的操作使其他线程可见吗
  • 如果在对象上使用volatile,并且对象引用发生更改。如果旧引用缓存在一个线程CPU缓存中,会发生什么情况?GC会使其保持活动状态吗
  • 示例代码:

    class Test{
      volatile Data data;
    
    }
    
    Class Data{
     int x;
     int y;
    }
    
    
    data= new Data(); // happens-before relationship only on creation
    
     //writer
     Thread writerThread = new Thread(() -> {
        data.setX(a);
        data.setY(b);
       });
    
    
     //reader
     Thread readerThread = new Thread(() -> {
    
      // read here is not guaranteed visibility, x,y not volatile
       int x = data.getX(); 
       int y = data.getY();          
      });
    
  • 是的,
    发生在
    之前关系将保证这一点。而关键字也会在写入线程和读取线程之间构建
    发生在
    之前的关系
  • 使用易失性变量可以降低内存一致性的风险 错误,因为对易失性变量的任何写入都会建立 发生在与该对象的后续读取的关系之前 变数

  • java语言规范没有提到它,也没有提到关于如何实现volatile的任何特定机制,所以我想这取决于特定的JVM

  • 是的,volatile之前发生过,但在本例中仅发生在引用上。这就是成员不具有可见性的原因,对吗?@MohammadKarmi
    之前发生过
    不与任何引用绑定。如果threadA
    发生在threadB之前,则表示threadB可以看到任何变量,就像threadA一样。我理解。我已经编辑了post带有示例代码。在这种情况下,您无法保证x,y的可见性。因为在更改对象引用
    数据
    而不是x,y时,将执行之前发生的操作。因此,如果在对象创建数据后对其进行编辑,则x,y不会是最新的。对吗?@MohammadKarmi是的…我认为这更多地是关于
    原子
    读卡器线程先引用
    data
    ,然后访问
    x
    y
    。这些动作不是原子的,所以volatile不能保证
    x
    y
    的可见性。只有在
    syncronized
    块中访问
    data
    x
    时,synchronized关键字才能做到这一点。我已经编辑了我用完整的代码进一步解释了这篇文章,这个可见性不是原子的吗?因为一个线程读取另一个线程写入。当读取x,y时,我无法从内存中获取它们,它们可能是缓存的,而不是最新的。关于你的第二个问题,标记为volatile的对象与任何其他对象一样被收集。@DavidSoroko这不是我的意思。我表示如果对象被缓存到其他线程,但它的引用被其他线程更改。是否应将其标记为删除?对象是可访问的还是不可访问的。如果不可访问,GC将堆内存“标记”为可用,并将其“扫掠”到可用内存列表中。