Java同步容器的不安全(Vector为例)。
Vector里一些写删操作的方法都是用synchronized实现同步,这样vecotor在使用时真的不需要考虑线程安全问题吗?
Vector vector = new Vector(); public void put(String element){ if (!vector.contains(element)) vector.add(element); } }
这个例子主要用于向vector放入数据,放入数据前先判断集合中是否已经存在。如果不存在则放入。即最后的结果为vector集合中没有重复的元素存在。
尽管vector中的contains()方法和 add()方法都是同步的。但是组合应用时还是存在现场安全问题。下面分析下:
假如有两个线程同时进入put()方法,传递的参数都是一样的,例如 put("123")。当线程1执行if (!vector.contains(element)) 后还没有执行vector.add(element); 时,线程2进来了,此时vector.contains(element))还是返回false,这样的结果会导致两个123都加入到vector。所以是现场不安全的。
解决办法:
1、在方法内使用synchronized,(原子性)。
synchronized(this){ if (!vector.contains(element)) vector.add(element); } }
2、参考单例模式的双检索方式。
if (!vector.contains(element)){ synchronized(this){ if (!vector.contains(element)) { vector.add(element); } } }
总结:Vector 在方法上使用同步这样做本身没有解决多线程问题,反而,在引入了概念的混乱的同时,导致性能问题,因为 synchronized 的开销是巨大的:阻止编译器乱序 。
上一篇:
IDEA上Java项目控制台中文乱码