锁定老帖子 主题:缓存框架之AOP渐进实现
精华帖 (1) :: 良好帖 (3) :: 新手帖 (0) :: 隐藏帖 (7)
|
|
---|---|
作者 | 正文 |
发表时间:2010-07-20
最后修改:2010-07-20
OK,Cache层如何扩展并不是本篇的主题,我所提供的只是一个参照解决方案,大家完全可以自己去扩展实现。至于线程安全问题并不是要在cache上加锁,而是cacheName+cacheKey,实现方式可以将cache包装一层提供一个getAndPut的原子方法,可以参考AtomicInteger,或者如我回复的那样加双重检查(如下代码所示),毕竟CacheKey是一个保护类,小概率事件是不太会发生的.
Object value = findFromCache(policy.getCacheName(), cacheKey); if (value == null) { value = synchronizedExecutor.synchronizedExecute(new Callable<Object>() { @Override public Object call() throws Exception { Object value = findFromCache(policy.getCacheName(), cacheKey); if (value == null) { try { value = methodInvocation.proceed(); putInCache(policy, cacheKey, value); } catch (Throwable e) { throw new Exception(e); } } return value; } }, Maps.immutableEntry(policy.getCacheName(), cacheKey)) |
|
返回顶楼 | |
发表时间:2010-07-20
最后修改:2010-07-20
1 cache本身没有读写控制?
2 methodInvocation.proceed()执行的时候,cache可以读写吗? 3 多个线程可以以不同的参数,同时调用methodInvocation.proceed()? 4 这样double check多少影响些性能。 |
|
返回顶楼 | |
发表时间:2010-07-20
最后修改:2010-07-20
不错的,最近正在做这方面的东西,谢谢共享
|
|
返回顶楼 | |
发表时间:2010-07-20
哎,先看看这个
http://www.iteye.com/topic/670414 Google Collections 中的MapMaker就可以当缓存用 |
|
返回顶楼 | |
发表时间:2010-07-20
rain2005 写道 哎,先看看这个 http://www.iteye.com/topic/670414 Google Collections 中的MapMaker就可以当缓存用 MapMaker的代码没有具体看过,不过有个疑问: ComputingMap的Function在执行过程中,缓存是否可以读写? 1 如果不能,那么影响并发性能。 2 如果可以,那么多个线程可能同时以相同name调用Function,如果这些调用的返回值不同,那么ComputingMap无法知道到底那个返回值是最新版本。 |
|
返回顶楼 | |
发表时间:2010-07-20
whitesock 写道 rain2005 写道 哎,先看看这个
http://www.iteye.com/topic/670414 Google Collections 中的MapMaker就可以当缓存用 MapMaker的代码没有具体看过,不过有个疑问: ComputingMap的Function在执行过程中,缓存是否可以读写? 1 如果不能,那么影响并发性能。 2 如果可以,那么多个线程可能同时以相同name调用Function,如果这些调用的返回值不同,那么ComputingMap无法知道到底那个返回值是最新版本。 在仔细看下吧,Concurrent Map,线程安全的,没有问题的。 |
|
返回顶楼 | |
发表时间:2010-07-20
最后修改:2010-07-20
最大的好处是,弱引用版本的ConcurrentHashMap,gc友好,并发安全。
|
|
返回顶楼 | |
发表时间:2010-07-20
最后修改:2010-07-20
你没看明白。
ConcurrentHashMap线程安全不代表对Function的调用也是安全的。如果get方法中发现不命中,那么调用function。问题在于对这个Function的调用时,是否持有ConcurrentHashMap的锁?(ConcurrentHashMap在get方法中其实没有加锁) 1 如果是,那么影响并发性能。 2 如果不是,那么多个线程可能同时以相同name调用Function,如果这些调用的返回值不同,那么ConcurrentHashMap无法知道到底那个返回值是最新版本。也就无法保证put的数据是正确的。 |
|
返回顶楼 | |
发表时间:2010-07-21
关注一下后续的讨论。这个话题我很感兴趣
|
|
返回顶楼 | |
发表时间:2010-07-21
whitesock 说的场景可以概括成:
A、B、C代表线程 A从缓存中获取了i(10),然后减1,把10-1=9放入缓存; B从缓存中获取了i(10),然后加1,把10+1=11放入缓存; C从缓存中获取了i(10),然后乘2,把10*2=20放入缓存; 问题就是,不清楚A、B、C何时结束,所以也就不知道9、11、20哪个是最新的数据了。 如果要保证更新是按照多线程触发的顺序来的话,那么应该是对i加锁,而不是应该在Cache的get和put上加锁。 对i加锁的意思是,加、减、乘都是i的方法,在这些方法上加锁。 此时Cache只需要知道最后调用的put是最新数据就可以了。 不知道我的理解对不对 |
|
返回顶楼 | |