Java VM上的内存障碍和编码风格

时间:2010-10-18 23:37:35

标签: java scala concurrency

假设我有一个静态复杂对象,它由一个线程池定期更新,并在一个长时间运行的线程中或多或少地连续读取。对象本身总是不可变的,反映了最新状态。

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版本的奖励:)

2 个答案:

答案 0 :(得分:45)

答案 1 :(得分:4)

使用带有最终a和b字段的不可变Foo可以解决默认值的可见性问题,但同样会使theFoo变得不稳定。

我个人喜欢不可变的价值类,因为它们更难以滥用。