java lazy initialization holder_Lazy initialization / memoization without volatile

It appears the Java Memory Model does not define "refreshing" and "flushing" of the local cache, instead people only call it that way for simplicity, but actually the "happens-before" relationship implies refreshing and flushing somehow (would be great if you can explain that, but not directly part of the question).

This is getting me really confused combined with the fact that the section about the Java Memory Model in the JLS is not written in a way which makes it easy to understand.

Therefore could you please tell me if the assumptions I made in the following code are correct and if it is therefore guaranteed to run correctly?

It is partially based on the code provided in the Wikipedia article on Double-checked locking, however there the author used a wrapper class (FinalWrapper), but the reason for this is not entirely obvious to me. Maybe to support null values?

public class Memoized {

private T value;

private volatile boolean _volatile;

private final Supplier supplier;

public Memoized(Supplier supplier) {

this.supplier = supplier;

}

public T get() {

/* Apparently have to use local variable here, otherwise return might use older value

* see https://jeremymanson.blogspot.com/2008/12/benign-data-races-in-java.html

*/

T tempValue = value;

if (tempValue == null) {

// Refresh

if (_volatile);

tempValue = value;

if (tempValue == null) {

// Entering refreshes, or have to use `if (_volatile)` again?

synchronized (this) {

tempValue = value;

if (tempValue == null) {

value = tempValue = supplier.get();

}

/*

* Exit should flush changes

* "Flushing" does not actually exists, maybe have to use

* `_volatile = true` instead to establish happens-before?

*/

}

}

}

return tempValue;

}

}

Also I have read that the constructor call can be inlined and reordered resulting in a reference to an uninitialized object (see this comment on a blog). Is it then safe to directly assign the result of the supplier or does this have to be done in two steps?

value = tempValue = supplier.get();

Two steps:

tempValue = supplier.get();

// Reorder barrier, maybe not needed?

if (_volatile);

value = tempValue;

Edit: The title of this question is a little bit misleading, the goal was to have reduced usage of a volatile field. If the initialized value is already in the cache of a thread, then value is directly accessed without the need to look in the main memory again.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值