JUC包中并发安全集合

1、CopyOnWriteArrayList

  • CopyOnWriteArrayList是并发安全的ArrayList,采用写时复制的策略
  • Object[]属性用来存放数组的元素
  • ReentrantLock属性是一个独占锁,为了保证同时只能有一个线程操作数组,实现并发安全

1、add(E e)方法

2、get(int index)方法

  1. 先获取数组
  2. 通过下标访问数组元素
  • 整个过程没有上锁,从而导致的问题?——数据的弱一致问题
  • 假设线程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<String> array = new ArrayL st<String> (); 
独占锁
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

读锁的获取和释放:

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值