有什么方法可以告诉 java 线程重新加载缓存吗?

Is it any way to tell java threads to reload caches?

研究 some answers here about volatile 关键字行为我了解到针对 x86 架构的易失性读取 总是 从主内存发生,这非常昂贵。

考虑下一种情况: 我有一段代码可以由 3 个线程执行。类似的东西:

class Foo {
  private Bar bar;

  public Bar read () {
    return bar;
  }
  public void write(Bar bar) {
    this.bar = bar;
  }
}

而且我还知道,每隔一小段时间(假设 100 毫秒)从 3 个不同的线程发生读取,并且假设每年发生一次写入。要坚持上下文考虑 Bar 不可变 - 这个问题不涉及与这个对象的交互,它只是关于引用本身。

使 bar 易变将完成它的任务 - 无论哪个线程执行此读取,每次下一次读取都将以正确的数据结束。但它带来了非常高的成本——每次读取都是从主内存读取。

UPD:所以我的下一个问题是:在 JVM 上是否有任何方法可以避免从主内存读取的惩罚?也许通过使引用成为非易失性并告诉线程缓存的值可能无效,这样该线程每年只从主内存读取一次,而不是每 100 毫秒读取一次?或者至少让它比 main ram read 便宜。它也可以以非阻塞方式完成吗?也许有一种方法可以使用 happens-before?

使用rw_locks 见 http://tutorials.jenkov.com/java-concurrency/read-write-locks.html ;这允许在只读时没有锁定,并且只有在有写入器时才具有(硬)锁定

如果您希望您的线程正常重用以前的值(即使它已过时)但偶尔检查更新,只需这样做:

int hits=0;
Bar cache=foo.read();  // Foo.bar is volatile
while(/*...*/) {
  if(++hits==100) {
    hits=0;
    cache=foo.read();
  }
  cache.doStuff();
}

如果你想打包这个逻辑(因为不是所有的查找都来自一个函数),添加一个间接层并且每个线程CountFoo 所以您没有共享点击计数器(或为线程本地存储付费)。