在研究some answers here about x86关键字行为时,我了解到,以x86架构为目标的易失性读取总是发生在主内存中,这是相当昂贵的。
考虑下一种情况:我有一个由3个线程执行的代码块。大概是这样的:
class Foo {
private Bar bar;
public Bar read () {
return bar;
}
public void write(Bar bar) {
this.bar = bar;
}
}
我还知道每隔一小段时间(比如说100ms)就会从3个不同的线程进行读取,而写入则会发生,比如说一年一次。根据上下文考虑,Bar是不可变的--这个问题不涉及与这个对象的交互,它只是关于引用本身。
让bar变成易失性将完成它的任务--每次下一次读操作,无论哪个线程执行这个读操作,都会得到正确的数据。但它带来了非常高的成本-每次读取都是从主存读取。
UPD:所以我的下一个问题是:在JVM上有什么方法可以避免从主存读取的损失吗?也许通过将引用设为非易失性,并告诉线程缓存值可能无效,所以这个线程一年只从主内存中读取一次,而不是每100ms读取一次?或者至少让它比main ram read便宜。它也可以以非阻塞的方式完成吗?也许有一种方法可以使用发生之前
发布于 2018-10-15 05:25:01
如果您希望您的线程正常重用以前的值(即使它已经过期),但偶尔检查更新,只需这样做:
int hits=0;
Bar cache=foo.read(); // Foo.bar is volatile
while(/*...*/) {
if(++hits==100) {
hits=0;
cache=foo.read();
}
cache.doStuff();
}
如果你想打包这个逻辑(因为并不是所有的查找都来自一个函数),添加一个间接层,并且每个线程有一个CountFoo
,这样你就不会共享命中计数器(或者为线程本地存储付费)。
发布于 2018-10-15 03:40:33
使用rw_locks查看http://tutorials.jenkov.com/java-concurrency/read-write-locks.html;这允许在只读时没有锁定,只有在有写入器时才有(硬)锁定
https://stackoverflow.com/questions/52806397
复制相似问题