前言
像 ArrayList、LinkedList、HashMap 这些容器都是非线程安全的,如果有多个线程并发地访问这些容器时,就会出现问题。因此,在编写程序时,必须要求程序员手动地在任何访问到这些容器的地方进行同步处理,这样导致在使用这些容器的时候非常地不方便。
所以,Java 提供了同步容器供用户使用。
同步容器分为以下几类
- List -> Vector,Stack
- Map -> HashTable
- Collections.synchronizedXXX(List、Set、Map)
同步容器的缺陷
性能问题
锁粒度大,进行同样多的插入操作,Vector 的耗时是 ArrayList 的两倍。
另外,由于 Vector 中的 add 方法和 get 方法都进行了同步,因此,在有多个线程进行访问时,如果多个线程都只是进行读取操作,那么每个时刻就只能有一个线程进行读取,其他线程便只能等待,这些线程必须竞争同一把锁。。
线程不是绝对安全(list集合)
例如有两个线程,线程A根据size的值循环执行remove操作,而线程B根据size的值循环执行执行get操作。它们都需要调用size获取容器大小,当循环到最后一个元素时,若线程A先remove了线程B需要get的元素,那么就会报越界错误。
单线程环境下的解决方法:Itr 类中给出了一个 remove()方法。但是在多线程并不适用,因为 Iterator.remove()并不是安全的。
总结
由上文可知,同步容器存在性能问题,又难做到完全的线程安全。这个时候我们就需要使用并发容器。