1、CopyOnWriteArrayList
- CopyOnWriteArrayList是并发安全的ArrayList,采用写时复制的策略
![](https://img-blog.csdnimg.cn/657fe1b1be8a460d9a2d04b87781946a.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5YyX6IiqX0N1cnJ5,size_10,color_FFFFFF,t_70,g_se,x_16)
- Object[]属性用来存放数组的元素
- ReentrantLock属性是一个独占锁,为了保证同时只能有一个线程操作数组,实现并发安全
1、add(E e)方法
![](https://img-blog.csdnimg.cn/9ba94e58b2c34773b6d90125fed61822.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5YyX6IiqX0N1cnJ5,size_20,color_FFFFFF,t_70,g_se,x_16)
2、get(int index)方法
- 先获取数组
- 通过下标访问数组元素
- 整个过程没有上锁,从而导致的问题?——数据的弱一致问题
- 假设线程A在获取数组元素的过程中,另外一个线程B删除了这个元素,因为删除时时用写时复制的策略(先复制,再删除,再替换),导致A线程读取到的是B线程删除前的原数组的数据。
3、remove(int index)方法
2、读写锁ReentrantReadWriteLock
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
读锁的获取和释放:
- 读取数据前先获取读锁,如果当前有其他线程持有写锁,就会被阻塞。否则直接获取读锁。
- 可以允许多个线程同时持有读锁