public static void main(String[] args) {
List<String> list = new CopyOnWriteArrayList<>();
list.add("1");
list.add("2");
list.add("3");
list.add("4");
new Thread(new Runnable() {
@Override
public void run() {
for (String s : list) {
try {
Thread.sleep(1100);
System.out.println(s);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
list.clear();
System.out.println("size:" + list.size());
}
CopyOnWriteArrayList是Arraylist的线程安全版本, 所有的修改操作(add、set等方法)其实都是通过创建底层数组的副本来实现的(在复制的副本上进行修改)。- CopyOnWriteArrayList 注释
CopyOnWriteArrayList 顾名思义就是在写(修改)这个ArrayList时,其内部会复制一个副本,修改(增、删)操作在副本上进行,操作完成后,将数据的引用指向修改后的副本。这就是CopyOnWriteArrayList 内部原理!
⚠️需要注意的是:CopyOnWriteArrayList内部, 所有的修改操作都是加锁的 !!! ,即修改操作之间是互斥的。
我们以add操作为例,画图演示一下add操作的过程:
根据上图我们总结一下:
CopyOnWriteArrayList 适用场景
1、读多写少
2、读操作可以尽可能的快,而写即使慢一些也没关系
CopyOnWriteArrayList 的读写规则
CopyOnWriteArrayList 缺点
1、数据副本占用额外的内存空间
2、在元素较多或者复杂的情况下,复制的开销很大
3、数据一致性问题
由于读写不是互斥的,所以修改副本后,“更改引用”前,其他线程读到的数据仍然是修改前的数据。