多线程并发中的ConcurrentHashMap绝对线程安全问题

ahpop 2013-04-05 12:58:15
多线程通讯中,发线,ConcurrentHashMap不是绝对线程安全的,就是用CLASS销都不行。
public class ManageData {

public static ConcurrentHashMap<SocketAddress,Message> hm =new ConcurrentHashMap<SocketAddress, Message>();
private static byte[] lock= new byte[0];

public void addMessage(SocketAddress client, Message message){
synchronized(lock){
hm.put(client, message);
}
}

public Message getMessageObject(SocketAddress address){
Message ret =null;
ret=hm.get(address);
if(null==ret){
ret=new Message();
synchronized(lock){
hm.put(address, ret);
}
}
return ret;
}



在调用getMessageObject()时老是出现前面的key已经放进去了。后面的会再放一次,覆盖了前面的对象。出错
...全文
659 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
ahpop 2013-04-06
  • 打赏
  • 举报
回复
引用 1 楼 DirectRay 的回复:
你代码的问题罢了。没有在add的时候做非空检验,却在取的时候对空作特殊处理,想不出问题都难呢。想避免的话,在add里对插入null的情况做处理即可。
放的时候做了非空检验,代码在另一个类中。
ahpop 2013-04-06
  • 打赏
  • 举报
回复
引用 4 楼 aalansehaiyang52 的回复:
有可能第一个线程调用addMessage中的同步块方法,但put还没有执行完,map.get(key)为空 第二个线程已经执行到判断hm.get(address);为null,等第一个线程释放对象锁后,就执行hm.put(address, ret);操作, 所以后面才会再放一次 public Message getMessageObject(SocketAddress address……
就如你讲的一样,是在第一个线程同步的时候,PUT还没有执行完,第二个线程已经执行了。改成上面的代码行是行,就是颗粒度有点大。
微观技术 2013-04-06
  • 打赏
  • 举报
回复
改成双否判断

   public Message getMessageObject(SocketAddress address){
        Message ret =null;
        ret=hm.get(address);
        if(null==ret){
            synchronized(lock){
				if((ret=hm.get(address))==null){
					ret=new Message();
					hm.put(address, ret);
				}
            }
        }
        return ret;
    }
微观技术 2013-04-05
  • 打赏
  • 举报
回复
ConcurrentHashMap 作为原子组件是线程安全的,但是目标类的编码有问题,整体变成了非线程安全的了
微观技术 2013-04-05
  • 打赏
  • 举报
回复
有可能第一个线程调用addMessage中的同步块方法,但put还没有执行完,map.get(key)为空 第二个线程已经执行到判断hm.get(address);为null,等第一个线程释放对象锁后,就执行hm.put(address, ret);操作, 所以后面才会再放一次 public Message getMessageObject(SocketAddress address){ synchronized(lock){ Message ret =null; ret=hm.get(address); if(null==ret){ ret=new Message(); hm.put(address, ret); } return ret; }
DirectRay 2013-04-05
  • 打赏
  • 举报
回复
你代码的问题罢了。没有在add的时候做非空检验,却在取的时候对空作特殊处理,想不出问题都难呢。想避免的话,在add里对插入null的情况做处理即可。
DirectRay 2013-04-05
  • 打赏
  • 举报
回复
你代码的问题罢了。没有在add的时候做非空检验,却在取的时候对空作特殊处理,想不出问题都难呢。想避免的话,在add里对插入null的情况做处理即可。
DirectRay 2013-04-05
  • 打赏
  • 举报
回复
你代码的问题罢了。没有在add的时候做非空检验,却在取的时候对空作特殊处理,想不出问题都难呢。想避免的话,在add里对插入null的情况做处理即可。

25,985

社区成员

发帖
与我相关
我的任务
社区描述
高性能WEB开发
社区管理员
  • 高性能WEB开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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