JUC常见的并发工具类

第20讲 并发工具类

同步容器及其注意事项
方法用synchronized进行修饰,组合操作需要注意竞态条件问题,比如用迭代器遍历容器。
并发容器及其注意事项
CopyOnWriteArrayList
CopyOnWriteArrayList 读取是完全不用加锁的,并且更厉害的是:写入也不会阻塞读取操作。只有写入和写入之间需要进行同步等待。
CopyOnWriteArrayList 类的所有可变操作(add,set等等)都是通过创建底层数组的新副本来实现的。当 List 需要被修改的时候,我并不修改原有内容,而是对原有数据进行一次复制,将修改的内容写入副本。写完之后,再将修改完的副本替换原来的数据,这样就可以保证写操作不会影响读操作了。
所谓CopyOnWrite 也就是说:在计算机,如果你想要对一块内存进行修改时,我们不在原有内存块中进行写操作,而是将内存拷贝一份,在新的内存中进行写操作,写完之后呢,就将指向原来内存指针指向新的内存,原来的内存就可以被回收掉了。
CopyOnWriteArrayList 写入操作 add() 方法在添加集合的时候加了锁,保证了同步,避免了多线程写的时候会 copy 出多个副本出来。
使用场景:读多写少,且能够容忍短暂的不一致
ConcurrentHashMap 内部采用了分段锁机制
ConcurrentSkipListMap 使用跳表实现的线程安全Map
队列方面:阻塞于非阻塞,单端与双端能够进行组合。
在哈希冲突严重的情况下,ConcurrentSkipListMap的效果有可能会优于ConcurrentHashMap
BlockingQueue
ArrayBlockingQueue
ArrayBlockingQueue 是 BlockingQueue 接口的有界队列实现类,底层采用数组来实现。ArrayBlockingQueue一旦创建,容量不能改变。其并发控制采用可重入锁来控制,不管是插入操作还是读取操作,都需要获取到锁才能进行操作。当队列容量满时,尝试将元素放入队列将导致操作阻塞;尝试从一个空队列中取一个元素也会同样阻塞。
LinkedBlockingQueue 底层基于单向链表实现的阻塞队列,可以当做无界队列也可以当做有界队列来使用
PriorityBlockingQueue 是一个支持优先级的无界阻塞队列,默认情况下元素采用自然顺序进行排序,也可以通过自定义类实现 compareTo() 方法来指定元素排序规则,或者初始化时通过构造器参数 Comparator 来指定排序规则。 并发控制采用的是 ReentrantLock。
ConcurrentLinkedQueue
使用 CAS 非阻塞算法来实现的非阻塞队列
补充;什么是快速失败?什么是安全失败?
快速失败(fail-fast)
在使用迭代器对集合对象进行遍历的时候,如果 A 线程正在对集合进行遍历,此时 B 线程对集合进行修改(增加、删除、修改),或者 A 线程在遍历过程中对集合进行修改,都会导致 A 线程抛出 ConcurrentModificationException 异常。
为什么在用迭代器遍历时,修改集合就会抛异常时?
原因是迭代器在遍历时直接访问集合中的内容,并且在遍历过程中使用一个 modCount 变量。集合在被遍历期间如果内容发生变化,就会改变 modCount 的值。
每当迭代器使用 hashNext()/next() 遍历下一个元素之前,都会检测 modCount 变量是否为 expectedModCount 值,是的话就返回遍历;否则抛出异常,终止遍历。
安全失败(fail-safe)
采用安全失败机制的集合容器,在遍历时不是直接在集合内容上访问的,而是先复制原有集合内容,在拷贝的集合上进行遍历。
由于迭代时是对原集合的拷贝进行遍历,所以在遍历过程中对原集合所作的修改并不能被迭代器检测到,故不会抛 ConcurrentModificationException 异常

第21讲 原子类

无锁方案的实现原理
Java是如何实现原子化操作的
AtomicLong getAndIncrement()
unsafe.getAndAddLong()
该方法首先会在内存中读取共享变量的值,之后循环调用 compareAndSwapLong() 方法来尝试设置共享变量的值,直到成功为止。(经典do while实现)
compareAndSwapLong() 是一个 native 方法,只有当内存中共享变量的值等于 expected 时,才会将共享变量的值更新为 x,并且返回 true;否则返回false。
原子类概览
基本类型
数组类型
引用类型
对象的属性修改类型
原子化累加器
CAS问题
ABA问题
只能保证一个共享变量的原子操作
循环时间开销过大

第26讲 Fork/Join

ForkJoinTask是一个抽象类,定义分治任务
ForkJoinPool 定义执行分治任务的线程池
ForkJoinPool工作原理 双端窃取队列,能够让所有线程的工作量基本均衡

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值