【杂记】JUC高并发容器

1.java的基础容器有哪些?哪些是线程不安全的?哪些有是线程安全的?

java的基础容器有四大主要类:List、Set、Queue、Map四个大类,其中ArrayList、LinkedLsit、HashMap都是线程不安全的;VerCtor、HashTbale、SynchronizedList都是线程安全的。其中java还提供一组包装的方法,将一个普通的基础容器包装成一个线程安全的同步容器,例如:Collections.synchronized

2.JUC同步容器逻辑是什么?

实现了容器的操作接口,在操作接口上使用synchronized进行线程同步,然后在synchronized的临界区将实际的操作委托给被包装的基础容器。

3.理解高并发容器?

JUC同步容器是基于非阻塞算法(或者无锁编程算法)实现的容器类,无锁编程算法主要通过CAS+Volatile组合实现,通过CAS保障操作的原子性,通过volatile保障变量内存的可见性。

4.为什么采用无锁编程?

无锁编程有以下的优点:(1)开销较小:不需要在内核态和用户态之间进行切换;(2)读写不互斥:只有写操作需要使用基于CAS机制的乐观锁,读读操作之间可以不用互斥。

5.简单的说一下各个容器与高并发容器的区别?

(1)List:JUC包中的高并发List主要有CopyOnWriteArrayList,对应的基础容器为ArrayList。CopyOnWriteArrayList相当于线程安全的ArrayList,它实现了List接口。在读多写少的场景中,其性能远远高于ArrayList的同步包装容器。
(2)Set:JUC包中的Set主要有CopyOnWriteArraySet和ConcurrentSkipListSet。·CopyOnWriteArraySet继承自AbstractSet类,对应的基础容器为HashSet。其内部组合了一个CopyOnWriteArrayList对象,它的核心操作是基于CopyOnWriteArrayList实现的。·ConcurrentSkipListSet是线程安全的有序集合,对应的基础容器为TreeSet。它继承自AbstractSet,并实现了NavigableSet接口。ConcurrentSkipListSet是通过ConcurrentSkipListMap实现的。
(3)Map:JUC包中Map主要有ConcurrentHashMap和ConcurrentSkipListMap。·ConcurrentHashMap对应的基础容器为HashMap。JDK 6中的ConcurrentHashMap采用一种更加细粒度的“分段锁”加锁机制,JDK 8中采用CAS无锁算法。ConcurrentSkipListMap对应的基础容器为TreeMap。其内部的SkipList(跳表)结构是一种可以代替平衡树的数据结构,默认是按照Key值升序的。
(4)Queue:JUC包中的Queue的实现类包括三类:单向队列、双向队列和阻塞
队列。·ConcurrentLinkedQueue是基于列表实现的单向队列,按照FIFO(先进先出)原则对元素进行排序。新元素从队列尾部插入,而获取队列元素则需要从队列头部获取。·ConcurrentLinkedDeque是基于链表的双向队列,但是该队列不允许null元素。作为双向队列,ConcurrentLinkedDeque可以当作“栈”来使用,并且高效地支持并发环境。除了提供普通的单向队列、双向队列外,JUC拓展了队列,增加了可阻塞的插入和获取等操作,提供了一组阻塞队列,具体如下:·ArrayBlockingQueue:基于数组实现的可阻塞的FIFO队列。·LinkedBlockingQueue:基于链表实现的可阻塞的FIFO队列。·PriorityBlockingQueue:按优先级排序的队列。·DelayQueue:按照元素的Delay时间进行排序的队列。·SynchronousQueue:无缓冲等待队列。

6.简单的介绍一下写时复制?

其主要的思想是:如果有多个访问器,如果有多个访问器(Accessor)访问一个资源(如内存或者磁盘上的数据存储),它们会共同获取相同的指针指向相同的资源,只要有一个修改器(Mutator)需要修改该资源,系统就会复制一份专用副本(Private Copy)给该修改器,而其他访问器所见到的最初资源仍然保持不变,修改的过程对其他访问器都是透明的(Transparently)。COW的主要优点是如果没有修改器去修改资源,就不会创建副本,因此多个访问器可以共享同一份资源

7.CopyOnWriteArrayList其原理有了解吗?

CopyOnWriteArrayList是写时复制思想的一种典型实现,其含有一个指向操作内存的内部指针array,而可变操作是在array数组的副本上进行的。当元数需要被修改或者增加时,并不直接在array指向的原数组上操作,而是首先对array进行一次复制,将修改的内容写入复制的副本中。写中之后,在将内部指针array指向新的副本,这样就可以确保修改操作不会影响访问器的读取操作。

8.CopyOnWriteArrayList读取与写入操作?

CopyOnWriteArrayList读取操作是没有任何同步控制和锁操作,理由是内部数组array不会发生修改,只会被另一个array替换,因此可以保证数据安全;写入操作add()方法在执行时加入独占锁以确保只能有一个线程进行写入操作,避免多线程写的时候会复制出多个副本。

9.CopyOnWriteArrayList有啥优点?

CopyOnWriteArrayList有一个显著的优点,那就是读取、遍历操作不需要同步,速度会非常快。所以,CopyOnWriteArrayList适用于读操作多、写操作相对较少的场景(读多写少),比如可以在进行“黑名单”拦截时使用CopyOnWriteArrayList。

10.CopyOnWriteArrayList和ReentrantReadWriteLock的比较

CopyOnWriteArrayList和ReentrantReadWriteLock读写锁的思想非常类似,即读读共享、写写互斥、读写互斥、写读互斥。但是前者相比后者的更进一步:为了将读取的性能发挥到极致,CopyOnWriteArrayList读取是完全不用加锁的,而且写入也不会阻塞读取操作,只有写入和写入之间需要进行同步等待,读操作的性能得到大幅度提升。

11.BlockingQueue(阻塞队列)的特点?

阻塞队列与普通队列之间的最大不同点在与阻塞队列提供了阻塞式的添加和删除方法,(1)阻塞添加:阻塞添加是指当阻塞队列元素已满时,队列会阻塞添加元素的线程,直到队列元素不满时,才重新唤醒线程执行元素添加操作。(2)阻塞删除:阻塞删除是指在队列元素为空时,删除队列元素的线程将被阻塞,直到队列不为空时,才重新唤醒删除线程,再执行删除操作。

12.常见的BlockingQueue有哪些?

(1).ArrayBlockingQueue,基于数组实现的,其内部使用一个定长数组来存储元素,除了一个定长数组外。ArrayBlockingQueue内部还保存着两个整型变量,分别标识着队列的头部和尾部在数组中的位置。但其无法并行运行,其原因是添加和删除操作共用通一个锁对象。
(2).LinkedBlockingQueue,基于链表的阻塞队列,其内部也维护着一个数组缓存队列(改队列有一个链表构成),LinkedBlockingQueue对于添加和删除分别采用了独立的锁来控制数据的同步,也就意味着在高并发的情况下,生成者和消费者可以并行的操作队列中的数据,以此来提高整个队列的并发性能。
(3).DelayQueue,中的元素只有当其指定的延迟时间到了,才能够从队列中获取该元素,DelayQueue是一个没有大小限制的队列,因此往队列中添加数据的操作(生产者)永远不会被阻塞,而只有获取数据的操作(消费者)才会阻塞。常用来管理一个超时未响应的连接队列。
(4).PriorityBlockingQueue,并不会阻塞数据生产者,而只会在没有可消费的数据时,阻塞数据的消费者。在使用的时候要特别注意,生产者生产数据的速度绝对不能快于消费者消费数据的速度,否则时间一长,会最终耗尽所有的可用堆内存空间。
(5).SynchronousQueue,一种无缓冲的等待队列,类似于无中介的直接交易,有点像原始社会中的生产者和消费者,生产者拿着产品去集市销售给产品的最终消费者,而消费者必须亲自去集市找到所要商品的直接生产者,如果一方没有找到合适的目标,那么大家都在集市等待。

13.对ConcurrenHashMap有了解吗?

ConcurrentHashMap是一个常用的高并发容器类,也是一种线程安全的哈希表。Jave7以及之前版本的ConcurrenHashMap使用Segment(分段锁)技术将数据分成一段一段存储,然后给每一段数据配一把锁,当线程占用锁访问其中一段数据的时候,其他段的数据也能被其他线程访问,能够实现真正的并发访问,ConcurrentHashMap和同步容器HashTable的主要区别在锁的类型和粒度上:HashTable实现同步是利用synchronized关键字进行锁定的,其实是针对整张哈希表进行锁定的,即每次锁住整张表让线程独占,虽然解决了线程安全问题,但是造成了巨大的资源浪费。
14.1.7版本的ConcurenHashMap与1.8版本的区别?
JDK 1.7的ConcurrentHashMap的锁机制基于粒度更小的分段锁,分段锁也是提升多并发程序性能的重要手段之一,和LongAdder一样,属于热点分散型的削峰手段。分段锁其实是一种锁的设计,并不是具体的一种锁,对于ConcurrentHashMap而言,分段锁技术将Key分成一个一个小Segment存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一段数据的时候,其他段的数据也能被其他线程访问,能够实现真正的并发访问。ConcurrentHashMap的内部结构的层次关系为ConcurrentHashMap→Segment→HashEntry。这样设计的好处在于,每次访问的时候只需要将一个Segment锁定,而不需要将整个Map类型集合都锁定。
在JDK 1.8中,ConcurrentHashMap已经抛弃了Segment分段锁机制,存储结构采用数组+链表或者红黑树的组合方式,利用CAS+Synchronized来保证并发更新的安全。虽然JDK 1.8对ConcurrentHashMap的内部结构进行了改进,改采用数组+链表或红黑树来实现,但是从Segment(分段锁)技术角度来说,其原理是类似的。ConcurrentHashMap的内部结构的层次关系为ConcurrentHashMap→链式桶/树状桶。这样设计的好处在于,每次访问的时候只需对一个桶进行锁定,而不需要将整个Map集合都进行粗粒度的锁定。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值