论坛首页 入门技术论坛

ConcurrentHashMap真的有必要吗

浏览 14078 次
该帖已经被评为新手帖
作者 正文
   发表时间:2012-04-23  
aa87963014 写道
接上面,由于操作map的这5个方法都没有同步,所以就算用了ConcurrentHashMap也是非线程安全的,反之如果这5个方法都实现了同步,那么map就算是使用hashmap也是线程安全的

如果5个方法都同步了也未必是安全的。
0 请登录后投票
   发表时间:2012-04-23  
aa87963014 写道

ConcurrentHashMap真的有必要吗,很多时候我们用ConcurrentHashMap来保证操作map的过程达到线程安全,

但是跟多的时候map是用来存储临时数据例如User信息

 

假设在一个单例类里面设置了一个共享变量map作为存储User的集合,

 

你还有一个方法是用来操纵map里面的user例如:

 

 

public void a(){
  User user=map.get("1");

  user.xxxxxxx

  Thread.sleep(1000*5);

  map.put("1",user);

}

 为了明显看到效果,加上了线程sleep 5秒,a方法是非线程安全的。

 

我想知道的是,在这种情况下,这个map是否是线程安全有什么关系?ConcurrentHashMap能保证put、get操纵达到线程安全,但是只能局限于自身,对于这个方法、业务来说打不到线程安全的要求,map就算是线程安全的又有什么意义?

 

我的意思就好像一个球队输了,就算其中一个球员表现很抢眼又有什么意义?你说呢?

 

完全不明白楼主在说什么。如果你的map的作用范围只是在a方法里面,那是没什么关系,HashMap或ConcurrentHashMap 都可以。

 

但是当map是作为一个类的静态属性,或者用来做缓存,或者比如程序初始化时读取的相关配置属性。不仅仅是临时使用的。

或者是类的成员属性。比如:

static Map<String,String> map=new ConcurrentHashMap<String, String>();
	public void a(){  
		  User user=map.get("1");  
		  user.xxxxxxx  
		  Thread.sleep(1000*5);  
		  map.put("1",user);  
		}
 

这样方法a被多线程操作时,map如果是HashMap就会出错,而ConcurrentHashMap就安全。

另外map的get方法在多线程下也是安全的,只有put才是不安全的

 

 

1 请登录后投票
   发表时间:2012-04-23  
aa87963014 写道
另外一点,通常一个业务类会操作多个这种共享变量,这种情况下是否直接在method上面加锁就可以了?还是即便如此,为了让锁的粒度达到最小,在各个业务方法里面自行决定锁的范围

如果你的业务类会操作多个共享变量,那么你的这个业务类应该保证是线程安全的。换句话来说,使用你业务类的客户端代码不需要同步就能够保证共享数据的一致性。一般来说应该尽量让锁的范围最小。
0 请登录后投票
   发表时间:2012-04-23  
thetcc 写道
aa87963014 写道

ConcurrentHashMap真的有必要吗,很多时候我们用ConcurrentHashMap来保证操作map的过程达到线程安全,

但是跟多的时候map是用来存储临时数据例如User信息

 

假设在一个单例类里面设置了一个共享变量map作为存储User的集合,

 

你还有一个方法是用来操纵map里面的user例如:

 

 

public void a(){
  User user=map.get("1");

  user.xxxxxxx

  Thread.sleep(1000*5);

  map.put("1",user);

}

 为了明显看到效果,加上了线程sleep 5秒,a方法是非线程安全的。

 

我想知道的是,在这种情况下,这个map是否是线程安全有什么关系?ConcurrentHashMap能保证put、get操纵达到线程安全,但是只能局限于自身,对于这个方法、业务来说打不到线程安全的要求,map就算是线程安全的又有什么意义?

 

我的意思就好像一个球队输了,就算其中一个球员表现很抢眼又有什么意义?你说呢?

 

 

完全不明白楼主在说什么。如果你的map的作用范围只是在a方法里面,那是没什么关系,HashMap或ConcurrentHashMap 都可以。

 

但是当map是作为一个类的静态属性,或者用来做缓存,或者比如程序初始化时读取的相关配置属性。不仅仅是临时使用的。

或者是类的成员属性。比如:

 

static Map<String,String> map=new ConcurrentHashMap<String, String>();
	public void a(){  
		  User user=map.get("1");  
		  user.xxxxxxx  
		  Thread.sleep(1000*5);  
		  map.put("1",user);  
		}
 

这样方法a被多线程操作时,map如果是HashMap就会出错,而ConcurrentHashMap就安全。

另外map的get方法在多线程下也是安全的,只有put才是不安全的

 

 

要是get的话,哪个MAP都安全的,读貌似不存在线程不安全,但如果是put的话,就算是ConcurrentHashMap,也不一定是安全,除非是光光put,而没有其他原子操作集合。如果是原子操作集合,不一定就是线程安全,还得用关键字锁它才行。。其实就是等于在讨论hashmap跟hashtable的意义差不多的吧

0 请登录后投票
   发表时间:2012-04-23  
ConcurrentHashMap只是对自己进行原子操作,你的业务操作它不管,其实也管不了,天知道你的业务是怎样的,所以只能你自己控制,JDK1,5自带了各种原子容器、原子锁,你可以根据业务进行组合实现。
0 请登录后投票
   发表时间:2012-04-23  
你说的是业务的一致性...
0 请登录后投票
   发表时间:2012-04-23  
线程安全的追求应该到达什么样的地步,怎么评估线程不安全的隐患以及达到线程安全对程序性能的影响。

服务器的极限是什么,oom还是线程无线被阻塞。

在什么样的情况下才应该重视同步问题
0 请登录后投票
   发表时间:2012-04-23  
ConcurrentHashMap只保证对自己的get,put 并发操作时,是同步的,业务级别的同步,当然要自己控制.
就好像DB操作一样,对一条记录update,insert into操作根本不需要事务.因为不可能出现修改了几个字段,还有几个字段没候改的情况,单条操作的事务是由DB来作的,程序员根本不要管.
0 请登录后投票
   发表时间:2012-04-23  
按照LZ的思路,douglee是自作多情了
0 请登录后投票
   发表时间:2012-04-23  
有一点搞错了,ConcurrentHashMap的目的是达到自身的put、get操作线程安全,
作为一个容器,就算业务是同步的,如果map自身不是线程安全也白搭
0 请登录后投票
论坛首页 入门技术版

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