3 回答
TA贡献1773条经验 获得超3个赞
cache对象在service()中只有一处写操作(创建新的cache对象),其余都是读操作,这里符合volatile的应用场景,确保cache对象对其他线程的可见性,不会出现并发读的问题。
返回的结果是factors对象,factors是局部变量,并未使cache对象逸出,所以这里也是线程安全的。
TA贡献1831条经验 获得超4个赞
一下个人理解:
(1).cache对象在service()中只有一处写操作,但是多个线程都会执行这个写操作。比如A线程带入参数a1执行service方法之后,缓存里是number=a , lastFactors=[a];这时a2线程进入service方法带入a,执行BigInteger[] factors = cache.getFactors(i); 取得了缓存数据[a]进行判断时线程切换,来了个C线程带入参数c执行完了方法。实际上此时的缓存是c和[c].理论上线程B读的值已经是过期的了。。。只是因为“缓存”的业务意义使得这个过期值不会引起程序错误罢了。。。也就是说这个例子的线程安全体现在正好切合了这个业务。。。
(2).OneValueCache的不可变也是有限制的。BigInteger[]类型的数组接受外部参数后,用Arrays.copyOf能使得初始化后值不再变化。但是如果不是BigInteger类型而是其他类型,要保证该类型也是不可变对象才行。
总之我感觉,对于我这么菜的初学者来说,锁还是最好用的。毕竟程序的优化是建立在没有BUG的基础上。万一哪边因为理解偏差导致隐含漏洞就跪了。
TA贡献1780条经验 获得超1个赞
我觉得这个问题,对于常量类来说,多线程读的操作不存在线程安全问题,但是写的操作要看具体应用场景对于线程安全的定义。比如说《Java并发编程实战》那段,我觉得作者对于线程安全就是只看当前的cache,最后达成一个缓存的目的,至于这个缓存能不能立马用到不在乎,反正肯定有线程会用到的。
添加回答
举报