线程安全集合类

文章目录

  • 1. ConcurrentHashMap
  • 2. LinkedBlockingQueue 阻塞队列
  • 3. ConcurrentLinkedQueue
  • 4. CopyOnWriteArrayList

线程安全集合类_第1张图片
JDK1.7 hashmap采用数组加链表头插的方式,在扩容时会出现循环死链问题,A->B->C扩容后C->B->A AB BA出现循环死链。

1. ConcurrentHashMap

HashTable是线程安全的,但是HashTable只是单纯的方法层面上加上synchronized。虽然安全,锁粒度太大了,所以性能不好。
口述ConcurrentHashMap并非锁住整个方法,像HashTable它直接在方法层面上加锁,粒度太大,ConcurrentHashMap它只锁了节点锁了一个链,而不是对整个table锁住,比如说put方法,它只是在要插入时才会加锁,吧插入的这个链表锁住,那table初始化啊、以及如果说当前位置没有元素时它会以CAS方式将节点插入,这些都没有锁,只有在插入时而且这个位置还有节点时才会加锁,粒度更小,并发性更高。而且get方法的话根本就没有加锁,也不是像HashTable那样吧方法上都加个synchronized,ConcurrentHashMap的get方法的话因为有volatile修饰table,也就保证了每次获取到的值都是最新的,也就不需要加锁。

2. LinkedBlockingQueue 阻塞队列

两把锁分别锁队头和队尾,其实就是保证消费者和生产者可以同步拿到对应的锁,你放你的我拿我的。多个消费者的话只有一个能拿到锁进行消费。

3. ConcurrentLinkedQueue

ConcurrentLinkedQueue 的设计与 LinkedBlockingQueue 非常像:

  • 两把【锁】,同一时刻,可以允许两个线程同时(一个生产者与一个消费者)执行
  • dummy 节点的引入让两把【锁】将来锁住的是不同对象,避免竞争
  • 只是这【锁】使用了cas 来实现

例如之前讲的 Tomcat 的 Connector 结构时,Acceptor 作为生产者向 Poller 消费者传递事件信息时,正是采用了ConcurrentLinkedQueue 将 SocketChannel 给Poller使用
线程安全集合类_第2张图片

4. CopyOnWriteArrayList

写入时拷贝的思想,增删改操作会将底层数组拷贝一份,更改操作在新数组上执行,这时不影响其它线程的并发读,读-写并发,但可能读到的旧数据,有问题。

回顾:读写锁只是读读并发

你可能感兴趣的:(JUC并发编程,juc)