不可变对象

ningbohezhijun 2014-09-16 11:44:18
最近在看《Java 7并发编程实战手册》,遇到了个问题,希望大家帮忙。

问题是关于:不可变对象与线程安全,代码如下


@Immutable
class OneValueCache {
private final BigInteger lastNumber;
private final BigInteger[] lastFactors;

public OneValueCache(BigInteger i,
BigInteger[] factors) {
lastNumber = i;
lastFactors = Arrays.copyOf(factors, factors.length);
}

public BigInteger[] getFactors(BigInteger i) {
if (lastNumber == null || !lastNumber.equals(i))
return null;
else
return Arrays.copyOf(lastFactors, lastFactors.length);
}
}

可以看到OneValueCache是不可变对象。


@ThreadSafe
public class VolatileCachedFactorizer implements Servlet {
private volatile OneValueCache cache =
new OneValueCache(null, null);//这里是安全发布

public void service(ServletRequest req, ServletResponse resp) {
BigInteger i = extractFromRequest(req);
BigInteger[] factors = cache.getFactors(i);
if (factors == null) {
factors = factor(i);
//由于cache为volatile,所以最新值立即能让其它线程可见
cache = new OneValueCache(i, factors);
}
encodeIntoResponse(resp, factors);
}
}

但是我又该如何理解VolatileCachedFactorizer类是线程安全的。总感觉理不清,也不知道去理清这个问题的重点是哪里。
书上是这么解释的(我没有理解):
与cache相关的操作不会相互干扰,因为OneValueCache是不可变的,并且在每条相应的代码路径中只会访问它一次。通过使用包含多个状态变量的容器对象来维持不变性条件,并使用一个volatile类型的引用来确保可见性,使得VolatileCachedFactorizer在没有显示地使用锁的情况下仍然是线程安全的。

请点拨我一下,谢谢!
...全文
87 1 打赏 收藏 转发到动态 举报
写回复
用AI写文章
1 条回复
切换为时间正序
请发表友善的回复…
发表回复
wangweiah 2015-04-15
  • 打赏
  • 举报
回复
我的理解如下, 保证VolatileCachedFactorizer的线程安全无非是要做到两点: 1.cache 指向对象的引用对其他线程可见或是不可变。 2.cache 指向对象里面所有的域对其他线程是可见或是不可变。 你看,cache用volatile修饰可以保证引用对其他线程可见,即满足了第1条。 而且OneValueCache 里面域都用final修饰,即可以保证域是不可变的,既满足了第2条。

67,512

社区成员

发帖
与我相关
我的任务
社区描述
J2EE只是Java企业应用。我们需要一个跨J2SE/WEB/EJB的微容器,保护我们的业务核心组件(中间件),以延续它的生命力,而不是依赖J2SE/J2EE版本。
社区管理员
  • Java EE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧