Collections包下的容器

Collections.synchronizedList
Collections.synchronizedSet
Collections.synchronizedMap
或者Vector、HashTable实现线程安全

JUC包下的容器

由HashTable引出ConcurrentHashMap

  • HashTable是使用synchronized实现同步,是对一个大的数组加一把锁,锁住的是对象整体。
  • ConcurrentHashMap采用的是分段式锁,将大的Map拆分成N个晓得Segment,在put的时候会根据hash来确定具体存放在哪个segment中,Segment内部的同步机制是基于Lock操作的,每个Segment都会分配一把锁。这样访问不同数据段的时候就实现了并发访问。


ConcurrentHashMap

  • jdk1.7使用分割分段(segment),形式是Reentrantlock + segment数组+hashEntry数组+链表。
  • segment是一种可重入锁(ReentrantLock);HashEntry用于存储键值对数据。

  • Jdk1.8使用node数组,摒弃segment概念。形式为:node数组 + 链表/红黑树 + synchronized + cas
  • 其中node只能用于链表的情况下,当冲突链表达到一定阈值(8)时,链表会转换成红黑树。并发控制使用synchronized和cas来操作。
  • cas+volatile实现线程安全。

好处:
1.    JDK1.8再次实现降低了锁的粒度,JDK1.7版本锁的粒度是基于segment的,包含多个hashEntry,而JDK1.8锁的粒度就是HashEntry
2.    使用红黑树来优化链表
(从HashTable(所有线程都竞争一个synchronized,table锁)->concurrentHashMap(segment -> node)锁的粒度一直在降低)

CopyOnWriteArrayList、CopyOnWritArrayeSet

介绍:

通过创建底层数组的新副本来实现的。当List、Set需要被修改的时候,我们并不修改原有内容,而是对原有数据进行一次复制,将修改的内容写入副本。写完之后,再将修改完的副本替换原来的数据,这样就会保证读写共享操作了。