线程安全集合类

2023-12-14 20:02:46


在这里插入图片描述
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使用
在这里插入图片描述

4. CopyOnWriteArrayList

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

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

文章来源:https://blog.csdn.net/qq_51240148/article/details/134993405
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。