1、currenthashmap的分段锁技术?
并发map是javautil中的一个类,他是提供了线程安全的hashmap实现。
再jdk1.7以及之前的并发map实现线程安全的方法就是使用分段锁技术
原理:
其内部将数据分为若干个段(Segment),其数量和并发级别有关系,具体是 大于等于并发级别的最小的2的幂数
每个segment使用单独的ReentrantLock(分段锁)
如果设计不同的sgement,则可以并发执行,如果是同一个sgement则会进行锁的竞争和等待。
此设计的效率要高于synchronize的。
但是再jdk1.8之后,ConcuttentHashmap则放弃了ReentrantLock,而重新使用synchronized。其原因有下面几点:
1)、加入分段锁浪费空间
2)、生产环境中,map在放入时,竞争同一个锁的概率非常小,分段锁反而会造成更新等操作的长时间等待。
3)、提高GC的效率
- 减少内存开销:如果使用ReentrantLock则需要节点继承AQS来获得同步支持,增加内存开销,而1.8中只有头节点需要进行同步。
- 内部优化:synchronized则是JVM直接支持的,JVM能够在运行时作出相应的优化措施:锁粗化、锁消除、锁自旋等等。
新的Concurrenthashmap中使用的Synchronized管金子+CAS操作保证了线程安全。
关于分段锁:段sgemnet集成了重入锁reentrantLock,有了所得功能,,每个锁控制的是一段,,当每个Segment原来越大时,锁的粒度就会变得大些。
分段锁的优势在于保证在操作不同段的map的时候可以进行并发执行,操作同段map的时候,进行锁的竞争和等待,这相对于直接对整个map同步Synchronized是有优势的。
缺点在于分成很多段会比较浪费内存空间(不连续,碎片化),操作map时竞争统一分段锁的概率非常小时,分段锁分段锁反而会造成鞥更新等操作的长时间等待,当某个段很大时,分段锁的性能会下降。
2、currenthashmap的读是否要加锁,为什么?
再jdk1.8中 get的源码是没有加任何锁的
再jdk1.7中 是采用sgement+hashEntry+ReentrantLock的方式实现并发安全的
再jdk1.8中采用的是 Node+CAS+Synchronized来保证并发安全的
jdk1.8的实现是降低锁粒度&#x