有什么方法可以告诉 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
所以您没有共享点击计数器(或为线程本地存储付费)。
研究 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
所以您没有共享点击计数器(或为线程本地存储付费)。