为了账号安全,请及时绑定邮箱和手机立即绑定

有没有办法告诉java线程重新加载缓存?

有没有办法告诉java线程重新加载缓存?

繁星淼淼 2021-11-17 16:50:39
在这里研究了一些 关于volatile 关键字行为的答案,我了解到针对 x86 架构的 volatile 读取总是发生在主内存中,这是非常昂贵的。考虑下一种情况:我有一个代码块,可以由 3 个线程执行。类似的东西:class Foo {  private Bar bar;  public Bar read () {    return bar;  }  public void write(Bar bar) {    this.bar = bar;  }}而且我知道每隔一小段时间(假设为 100 毫秒)就会从 3 个不同的线程中读取,假设每年发生一次写入。为了坚持上下文考虑 Bar immutable - 这个问题不包括与这个对象的交互,它只是关于引用本身。使 bar 可变将完成它的任务 - 无论哪个线程执行此读取,每次下一次读取都会以正确的数据结束。但它带来了非常高的成本——每次读取都是从主内存读取。UPD:所以接下来我的问题是:在 JVM 上有什么方法可以避免从主内存读取的惩罚吗?也许通过使引用非易失性并告诉线程缓存值可能无效,因此该线程每年仅从主内存读取一次而不是每 100 毫秒?或者至少让它比main ram read便宜。它也可以以非阻塞方式完成吗?也许有一种方法可以使用happens-before来处理它?
查看完整描述

2 回答

?
桃花长相依

TA贡献1860条经验 获得超8个赞

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


int hits=0;

Bar cache=foo.read();  // Foo.bar is volatile

while(/*...*/) {

  if(++hits==100) {

    hits=0;

    cache=foo.read();

  }

  cache.doStuff();

}

如果您想打包此逻辑(因为并非所有查找都来自一个函数),请添加一个间接层并为CountFoo 每个线程设置一个,这样您就不会共享命中计数器(或为线程本地存储付费)。


查看完整回答
反对 回复 2021-11-17
?
侃侃无极

TA贡献2051条经验 获得超10个赞

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


查看完整回答
反对 回复 2021-11-17
  • 2 回答
  • 0 关注
  • 232 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信