HashMap进行put操作时遇到的并发问题

今天遇到了个问题,在全局服务器重启的时候,原有的4游戏逻辑服务器会马上再注册过来,通过多线程对HashMap进行操作,结果从后续的日志发现,id=1的数据丢失了查了一下原因,多线程环境下put还是可能会有问题 .

2013-10-22 18:59:55.098 INFO [pool-5-thread-3] - 注册房间开始 id=1,type=pve1003,ip=115.29.172.234,port=10104,count=0
2013-10-22 18:59:55.098 INFO [pool-5-thread-5] - 注册房间开始 id=3,type=pve1004,ip=115.29.172.234,port=10105,count=0
2013-10-22 18:59:55.098 INFO [pool-5-thread-4] - 注册房间开始 id=2,type=pvp1001,ip=115.29.172.234,port=10101,count=0
2013-10-22 18:59:55.099 INFO [pool-5-thread-1] - 注册房间开始 id=4,type=pve1002,ip=115.29.172.234,port=10103,count=0
2013-10-22 18:59:55.102 INFO [pool-5-thread-3] - 注册房间完成  id=1
2013-10-22 18:59:55.103 INFO [pool-5-thread-4] - 注册房间完成  id=2
2013-10-22 18:59:55.104 INFO [pool-5-thread-5] - 注册房间完成  id=3
2013-10-22 18:59:55.105 INFO [pool-5-thread-1]- 注册房间完成  id=4


void addEntry(int hash, K key, V value, int bucketIndex) {   
    Entry<K,V> e = table[bucketIndex];   
        table[bucketIndex] = new Entry<K,V>(hash, key, value, e);   
        if (size++ >= threshold)   
            resize(2 * table.length);   
    }  

发生在index相同的情况下,大家拿到的链头可能不是最新的,后一个会直接覆盖了前一个 
而且当多条线程检测到容量超过负载因子时,会能发生多次resize。 

小结一下:remove与put都是一样的,由于大家拿到的不是最新链头,只要大家在Entry数组的index相同时(经过hash后的index),就有可能出现后一个覆盖前一个的操作,即前一个的操作无效。 
可能产生的现象会是: 
1)put进行的data有可能丢失了 
2)一些通过remove(Object key)删除掉的元素(返回删除成功)又出来了。 
3)多线程检测到HashMap容量超过负载因子时会进行多次的resize,由于要rehash,所以消耗的性能也是巨大的。
 


考虑到这个方法只有在起服务器的时候会用到,而且,后续的关于rooms和areas的map读操作比较频繁,所以通过加同步块解决,比较合适!

// Room缓存 角色Id -- Room对象
	private final Map<Integer, Room> rooms = new HashMap<Integer, Room>();
	private final Map<String, List<Integer>> areas = new HashMap<String, List<Integer>>();
public synchronized Room registRoom(Channel channel, String type, int port,
			String clientIp, List<PlayerDTO> playerList) {
List<Integer> list = areas.get(room.getType());
		if (null == list) {
			list = new ArrayList<Integer>();
			areas.put(room.getType(), list);
		}
rooms.put(room.getId(), room);
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

流子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值