在这里研究了一些 关于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 每个线程设置一个,这样您就不会共享命中计数器(或为线程本地存储付费)。
侃侃无极
TA贡献2051条经验 获得超10个赞
使用 rw_locks 见http://tutorials.jenkov.com/java-concurrency/read-write-locks.html ;这允许在只读时没有锁定,并且只有在有写入者时才具有(硬)锁定
添加回答
举报
0/150
提交
取消