论坛首页 Java企业应用论坛

高速缓存实现

浏览 12064 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (15) :: 隐藏帖 (0)
作者 正文
   发表时间:2010-06-08  
你addElement的原子性是基于putIfAbsent是原子的,所以你还是用了concurrentHashMap内部的锁了,没看出什么特别有价值的地方
0 请登录后投票
   发表时间:2010-06-08  
tyzqqq 写道
getElement没必要加线程锁吧,它仅仅是取值

getElement()的确不需要锁!
0 请登录后投票
   发表时间:2010-06-08   最后修改:2010-06-08
wkoffee说:"你addElement的原子性是基于putIfAbsent是原子的,所以你还是用了concurrentHashMap内部的锁了,没看出什么特别有价值的地方".
说明如下:这里主要是想说明即便此时出现了多线程的情况,当第二个线程来请求获得对应key的value时,只要发现已经有第一个线程在创建对应value后,只需要等待第一个线程的结果就行了,这也就是为什么要使用Futuretask的目的,这样就可以很好的避免在创建比较消耗性能的value对象的性能损失.
0 请登录后投票
   发表时间:2010-06-09   最后修改:2010-06-09
kazy 写道
从另外的地方抄个例子过来,

ConcurrentHashMap<String,String> map; 
String getString(String name) { 
    String x = map.get(name); 
    if (x == null) { 
        x = new String(); 
        map.put(name, x); 
    } 
    return x; 
}

如果你只调用get(),或只调用put()时,ConcurrentHashMap是线程安全的。
但是,在你调用完get后,调用put之前,
如果有另外一个线程调用了map.put(name, x),
你再去执行map.put(name,x),
就很可能把前面的操作结果覆盖掉了。
所以,即使在线程安全的情况下,
你还是有可能违反原子操作的规则。

同意kazy的观点,在多个线程同时进入到null里的时候,eval 和future 可能会被创建很多个。
另外又看了一下putIfAbsent方法,大概意思是
if (!map.containsKey(key)) 
      return map.put(key, value);
  else
       return map.get(key);

如果这样的话,楼主首先使用有锁的map将future放入,保证此时map的future唯一,如果返回值是null说明是该线程首次放入,然后future做生成真正value的操作,这样感觉应该是可以的。

不过这样的话,是否一次就可以搞定value的值,而不需要while(true)了?
0 请登录后投票
   发表时间:2010-06-09  
关键点是LZ的cache是不能修改的吧。一旦put进去,就不会改了,其他线程只能分享胜利成果了。
所以线程安全了。
0 请登录后投票
   发表时间:2010-06-09  
kazy 写道
从另外的地方抄个例子过来,

ConcurrentHashMap<String,String> map; 
String getString(String name) { 
    String x = map.get(name); 
    if (x == null) { 
        x = new String(); 
        map.put(name, x); 
    } 
    return x; 
}

如果你只调用get(),或只调用put()时,ConcurrentHashMap是线程安全的。
但是,在你调用完get后,调用put之前,
如果有另外一个线程调用了map.put(name, x),
你再去执行map.put(name,x),
就很可能把前面的操作结果覆盖掉了。
所以,即使在线程安全的情况下,
你还是有可能违反原子操作的规则。

这个要顶。不知道LZ的需求会不会break这一条
0 请登录后投票
   发表时间:2010-06-09  
archerfrank 写道
关键点是LZ的cache是不能修改的吧。一旦put进去,就不会改了,其他线程只能分享胜利成果了。
所以线程安全了。

当然这里没有考虑到cache的修改问题,在实际应用中cache的修改问题是和业务场景挂钩的,也就所说的缓存策略的问题。
0 请登录后投票
   发表时间:2010-06-09  
hankesi2000 写道
kazy 写道
从另外的地方抄个例子过来,

ConcurrentHashMap<String,String> map; 
String getString(String name) { 
    String x = map.get(name); 
    if (x == null) { 
        x = new String(); 
        map.put(name, x); 
    } 
    return x; 
}

如果你只调用get(),或只调用put()时,ConcurrentHashMap是线程安全的。
但是,在你调用完get后,调用put之前,
如果有另外一个线程调用了map.put(name, x),
你再去执行map.put(name,x),
就很可能把前面的操作结果覆盖掉了。
所以,即使在线程安全的情况下,
你还是有可能违反原子操作的规则。

同意kazy的观点,在多个线程同时进入到null里的时候,eval 和future 可能会被创建很多个。
另外又看了一下putIfAbsent方法,大概意思是
if (!map.containsKey(key)) 
      return map.put(key, value);
  else
       return map.get(key);

如果这样的话,楼主首先使用有锁的map将future放入,保证此时map的future唯一,如果返回值是null说明是该线程首次放入,然后future做生成真正value的操作,这样感觉应该是可以的。

不过这样的话,是否一次就可以搞定value的值,而不需要while(true)了?

因为在利用FutureTask生成Value的过程中,有可能出现异常,所以这里需要while(true)来做轮询,知道对应key有一个对应的FutureTask放入Map中。
0 请登录后投票
   发表时间:2010-06-09  
kazy 写道
从另外的地方抄个例子过来,

ConcurrentHashMap<String,String> map; 
String getString(String name) { 
    String x = map.get(name); 
    if (x == null) { 
        x = new String(); 
        map.put(name, x); 
    } 
    return x; 
}

如果你只调用get(),或只调用put()时,ConcurrentHashMap是线程安全的。
但是,在你调用完get后,调用put之前,
如果有另外一个线程调用了map.put(name, x),
你再去执行map.put(name,x),
就很可能把前面的操作结果覆盖掉了。
所以,即使在线程安全的情况下,
你还是有可能违反原子操作的规则。

你提出的这个问题我个人觉得应该不会出现,因为在put前利用了putIfAbent来保证该key对应的FutureTask是第一次put到Map,如果不是第一次此时只需要等待已经put的FutureTask执行获得value的结果,然后分享胜利果实即可.
0 请登录后投票
   发表时间:2010-06-09  
soongbo 写道
kazy 写道
从另外的地方抄个例子过来,

ConcurrentHashMap<String,String> map; 
String getString(String name) { 
    String x = map.get(name); 
    if (x == null) { 
        x = new String(); 
        map.put(name, x); 
    } 
    return x; 
}

如果你只调用get(),或只调用put()时,ConcurrentHashMap是线程安全的。
但是,在你调用完get后,调用put之前,
如果有另外一个线程调用了map.put(name, x),
你再去执行map.put(name,x),
就很可能把前面的操作结果覆盖掉了。
所以,即使在线程安全的情况下,
你还是有可能违反原子操作的规则。

你提出的这个问题我个人觉得应该不会出现,因为在put前利用了putIfAbent来保证该key对应的FutureTask是第一次put到Map,如果不是第一次此时只需要等待已经put的FutureTask执行获得value的结果,然后分享胜利果实即可.


的确putIfAbent能够保证只有唯一一个key,不过可惜的是你在调用putIfAbent前,有可能多个线程一起计算同一个key的value

你觉得这个的开销大还是锁的开销大
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics