java中Collections.synchronized()的方法很好用~
有一次看到一个很优秀的同事写了以下一串代码,如下
private static volatile ConcurrentMap<String, Map<Integer, Set<String>>> all;
public void demo(){
...
Map<Integer, Set<String>> foo =Collections.synchronizedMap(new HashMap<Integer, Set<String>>()); //point 1
...
Set<String> bar = Collections.synchronizedSet(preIdSet);//point 2
foo.put("ff",bar);
....
all.put("bb",foo);//point 3
}
我本能的提出质疑,我说你见过哪个源码有这样写过?我对源码的阅读虽然不多,却也不能算是孤陋寡闻。这样的写法就是很奇怪。
我提出每个类方法中的变量都是安全的。怎么可能需要同步呢?
他的解释是代码会被放入在point 3的all全局变量中,这样的解释是合理的。
因为all是全局变量,你把point 1和point 2放入里面后,的确会面临被其它线程的修改。
最近看书,思想总是会飘来飘去。我想起了这件事,就再次思考。
首先对于all这个变量,它已经是线程安全的了,何必再继续对内部的每个变量再进行一次同步操作呢,这样只会浪费性能。
举个例子,要想保证all变量的线程安全,必须保证all里面的对象A不能被同时修改。
既然A对象已经被锁住不能同时修改了,何必继续对A对象内部的a加锁呢?
修改a即是对A对象修改。所以它不可能被其他线程修改。
更正一下:
现在觉得以上想法是有问题的。
synchronized方法获得的对象 只保证对象的每个方法执行中是线程安全的。并不表示,方法结束后,它依然是线程安全的。
例如,线程安全的Map执行get(),会保证get中是线程安全的,但是get得到对象后,这个对象依然有可能被其他线程修改。