前言
我大概我是从去年12月份开始看书学习,到今年的6月份,一直学到看大家的面经基本上百分之90以上都会,我就在5月份开始投简历,边面试边补充基础知识等。也是有些辛苦。终于是在前不久拿到了字节跳动的offer,现在我也来写面经,希望能帮助到大家!
面经
Java基础
0.HashMap的源码,实现原理,JDK8中对HashMap做了怎样的优化。
拉链结构,数组+链表,原理是hash找数组,冲突后拉链表,1.8优化为会进化成红黑树提高效率,并且使用2^n来做容量值
引申点:
equal & hashcode
其他地方的hash处理,如redis的hash、集群slot等
对hash算法类型的了解(安全哈希和非安全哈希如mermerhash)
对hashMap实现的了解:取hashcode,高位运算,低位取模
一致性hash(处理了什么问题,在什么场景用到)
红黑树简单描述
1.HaspMap扩容是怎样扩容的,为什么都是2的N次幂的大小。
在容量到达抵达负载因子*最大容量的时候进行扩容,负载因子的默认值为0.75
2N的原因:
- hash的计算是通过hashcode高低位混合然后和容量的length进行与运算
- 在length=2n的时候,与运算相当于是一个取模操作
- 那么在每次rehash完毕之后mod2N的意义在于要么该元素是在原位置,要么是在最高位偏移多一位的位置,提高效率
引申点:
ConcurrentHashMap的扩容:1.7分段扩容以及1.8transfer并发协同的扩容
redis渐进式hash扩容处理
3.HashMap,HashTable,ConcurrentHashMap的区别。
Map线程不安全(没有用任何同步相关的原语),Table安全(直接加syn),Concurrent提供更高并发度的安全(分段锁思想orSyn+Cas)
引申点:
对线程安全的定义:如hashmap在1.7前会头插死循环,但是在1.8改善后还是不能叫线程安全,因为没有可见性
对锁粒度的思考:在介于map和table之间存在tradeoff之后的均衡解
Syn和ReentranceLock的区别
锁升级
4.极高并发下HashTable和ConcurrentHashMap哪个性能更好,为什么,如何实现的。
分两种情况讨论:
- 极高并发读:并发读的情况下,Table也为读加了锁,没有并发可言,ConcurrentMap读锁并没有加并发,直接可读,若读resize的某个tab为空则转到新tab去读,Node的元素val和指针next都是volatile修饰的,可以保证可见性,所以concurrentMap获胜
- 极高并发写:在并发写的情况下,table也是直接加了Syn做锁,强制串行,并且resize也只能单线程扩容,ConcurrentMap首先对于每个数组都有并发度,其次在resize的时候支持多线程协同,所以concurrentMap获胜
所以整体而言concurrentMap优势在于:
- 读操作基于volatile可见性所以无锁
- 写操作优势在于一是粗粒度的数组锁,二是协同resize
这个问题的思路是先分类讨论然后描述细节最后在下结论
引申点:
volatile的实现:保证内存可见、禁止指令重排序但无法保证原子性
java内存模型
JVM做的并行优化、先行发生原则与指令重排序
底层细节