假设我有一个静态复杂对象,它由一个线程池定期更新,并在一个长时间运行的线程中或多或少地连续读取。对象本身总是不可变的,反映了最新状态。
class Foo() { int a, b; }
static Foo theFoo;
void updateFoo(int newA, int newB) {
f = new Foo();
f.a = newA;
f.b = newB;
// HERE
theFoo = f;
}
void readFoo() {
Foo f = theFoo;
// use f...
}
我至少不关心我的读者是看到旧的还是新的Foo,但是我需要看到一个完全初始化的对象。 IIUC,Java规范说没有HERE中的内存屏障,我可能会看到f.b初始化但f.a尚未提交到内存的对象。我的程序是一个真实世界的程序,迟早会将内容提交到内存中,所以我不需要立即将theFoo的新值提交到内存中(尽管它不会受到伤害)。
您认为实现内存障碍最可读的方式是什么?如果需要,我愿意为了可读性而付出一点性能价格。我想我可以将赋值同步到Foo,这样可行,但是我不确定读取代码的人为什么这么做是非常明显的。我还可以同步新Foo的整个初始化,但这会引入更多实际需要的锁定。
你怎么写它以使它尽可能可读? 对Scala版本的奖励:)
答案 0 :(得分:45)
答案 1 :(得分:4)
使用带有最终a和b字段的不可变Foo可以解决默认值的可见性问题,但同样会使theFoo变得不稳定。
我个人喜欢不可变的价值类,因为它们更难以滥用。