欢迎您访问365答案网,请分享给你的朋友!
生活常识 学习资料

JUC包中并发安全集合

时间:2023-06-14
1、CopyonWriteArrayList

CopyOnWriteArrayList是并发安全的ArrayList,采用写时复制的策略Object[]属性用来存放数组的元素ReentrantLock属性是一个独占锁,为了保证同时只能有一个线程操作数组,实现并发安全1、add(E e)方法 2、get(int index)方法 先获取数组通过下标访问数组元素

整个过程没有上锁,从而导致的问题?——数据的弱一致问题假设线程A在获取数组元素的过程中,另外一个线程B删除了这个元素,因为删除时时用写时复制的策略(先复制,再删除,再替换),导致A线程读取到的是B线程删除前的原数组的数据。3、remove(int index)方法

其实和新增元素的代码类似,首先获取独占锁以保证删除数据期间其他线程不能对 array 进行修改,然后获取数组中要被删除的元素,并把剩余的元素复制到新数组,之后使用新数组替换原来的数组,最后在返回前释放锁。 2、读写锁ReentrantReadWriteLock 

解决线程安全 题使用 ReentrantLock 就可以 , 但是 Ree ntrantLock 是独占锁 某时只个线程可以获取该锁,而实际中会有写少读多的场景,显然 ee ntrantLock 满足不了这个需求,所以 Ree ntrantR ea dWrit eLock 应运而生 ReentrantReadWriteLock 采用 读写分 离的策略,允许多个线程可以同时获取读锁。 内部维护了读锁ReadLock()和写锁WriteLock()两个方法读写锁本质上也是通过AQS原理实现的,32位的state变量的低16位表示写锁的重入次数,高16位表示读锁的重入次数。

private ArrayList array = new ArrayL st (); 独占锁private final ReentrantReadWr teLock lock =口ew ReentrantReadWriteLock() ; private final Lock readLock = lock.readLock () ; private final Lock writeLock = lock 、writeLock (); //添加元素public void add (String e) { writeLock 、lock (); try { array、add (e ) ; } finally { writeLock.unlock() ; //删除元素public void remove (String e) { writeLock.lock () ; try { array 、remove(e) ; } finally { writeLock、unlock() ; //获取数据public Stri ng get (int index ) { readLock 、lock() ; try { retur array get(index)} finally { readLock.unlock() ;

写锁的获取lock()和释放unlock():

在修改、添加、删除时要首先获取写锁,如果现在又其他线程持有写锁会被阻塞;如果没有线程持有写锁,则获取写锁,state的低16位+1,并把当前持有锁的线程设置为本线程。释放写锁的时候state的低16位-1读锁的获取和释放:

读取数据前先获取读锁,如果当前有其他线程持有写锁,就会被阻塞。否则直接获取读锁。可以允许多个线程同时持有读锁

Copyright © 2016-2020 www.365daan.com All Rights Reserved. 365答案网 版权所有 备案号:

部分内容来自互联网,版权归原作者所有,如有冒犯请联系我们,我们将在三个工作时内妥善处理。