问:
说说ArrayList,StringBuilder,HashMap为啥线程不安全?
面试官心里:
考察面试者对常见问题的深入理解程度以及是否有看源码的习惯。
答:
1,翻开Vector,StringBuffer,Hashtable的源码,第一个印象就是synchronized这个关键词不要钱的,往上堆就行了,所以,这几个类肯定是线程安全的了。
2,但是这些类完成的功能是否都需要在多线程环境下呢?显然不是,所以 ArrayList,StringBuilder,HashMap就出现了。
ArrayList
在多个地方不安全,例如:
- 判断集合大小,再添加元素,容易数组越界
- 判断集合大小,添加元素,不越界但可能会相互覆盖
StringBuilder
在扩容,给字符数组同一个位置赋值时,会相互覆盖
HashMap
- 在扩容阶段(size*2)容易出现线程不安全
- >> 扩容会重新计算hash,重新分桶,两个线程操作,容易形成循环依赖(jdk1.7出现,jdk1.8因为用红黑树优化,不会出现死循环)
- >> 扩容会重新计算hash,重新分桶,两个线程操作,一个成功扩容,另外一个数据就会丢失(1.7和1.8都会出现)。
- 在put阶段:先计算hash的位置,再赋值,两步操作,容易出现线程安全问题,覆盖前值(1.7和1.8都会出现)。
- 使用ConcurrentHashMap处理并发情况