同步容器的所有操作一定是线程安全的吗

例如 Vector
如下方法都是synchronized
同步容器的所有操作一定是线程安全的吗_第1张图片
同步容器的所有操作一定是线程安全的吗_第2张图片
同步容器的所有操作一定是线程安全的吗_第3张图片
等等
synchronized的方法可以在多线程中单独使用
虽然同步容器的方法加了锁,但是对于复合操作 无法保证线程安全。

举一个例子,我们定义如下删除Vector中最后一个元素方法:

public Object deleteLast(Vector v) {
     
	int lastIndex = v.size() - 1;
	v.remove(lastIndex);
}

上面这个方法是一个复合方法,包括size()和remove(),看上去好像并没有什么问题,size()\remove()都是线程安全的,那deleteLast方法应该也是线程安全的

但是可能会抛异常,remove可能抛出ArrayIndexOutOfBoundsException
当索引值不再有效时,会抛出异常

线程2在删除时,在之前线程1先删除了,所以抛异常
为了避免 ,可以加上锁,如下:

public Object deleteLast(Vector v) {
     
	synchronized(v) {
     
		int lastIndex = v.size() - 1;
		v.remove(lastIndex);
	}
}

不同线程同一时间操作同一个Vector,其中包括删除操作,那么就可能发生线程安全问题。所以,在使用同步容器的时候,如果涉及到多个线程同时执行删除操作,就要考虑下是否需要加锁

虽然加上锁可以解决以上的线程安全问题,但是效率降低了
为此
jdk5.0开始, java.util.concurrent包下提供了多种并发容器来改进同步容器的性能

上文的同步容器的复合操作的问题,在Map中发生的比较多,所以在ConcurrentHashMap中增加了对常用复合操作的支持,比如"若没有则添加":putIfAbsent(),替换:replace()。这2个操作都是原子操作,可以保证线程安全

复合操作包括迭代(反复获取元素,直到容器中的最后一个元素)、导航(根据一定顺序查找下一元素)、条件运算(“若不存在则添加”,“若存在则删除”)

你可能感兴趣的:(java,多线程)