Java并发包中的并发list只有CopyOnWriteArrayList。CopyOnWriteArrayList是一个线程安全的ArrayList,对其进行的修改操作都是在底层的一个复制数组(快照)上进行的,也就是使用了写时复制策略。
写时复制(CopyOnWrite,简称COW)思想是计算机程序涉及领域中的一种优化策略。其核心思想是,如果多个调用者(Callers)同时要求相同的资源(如内存或者磁盘上的数据存储),他们会共同获取相同的指针指向相同的资源,直到某个调用者试图修改资源内容时,系统才会真正复制一份专用的副本给调用者,而其他调用者所见到的最初的资源仍然保持不变。
此做法主要的优点是如果调用者没有修改资源,就不会有副本被创建,因此多个调用者只是读取操作时可以共享同一份资源。
在CopyOnWriteArrayList的类图中,每个CopyOnWriteArrayList对象里面有一个array数组对象用来存放具体元素,ReentrantLock独占锁对象用来保证同时只有一个线程对array进行修改。
弱一致性的迭代器:
所谓弱一致性是指返回迭代器后,其他线程对list的增删改查对迭代器是不可见的。
CopyOnWrite的应用场景:
CopyOnWrite并发容器用于读多写少的并发场景。比如白名单,黑名单,商品类目的访问和更新场景,假如我们有一个搜索网站,用户在这个网站的搜索框中,输入关键字搜索内容,但是某些关键字不允许被搜索。这些不能被搜索的关键字会被放在一个黑名单中,黑名单每天晚上更新一次。当用户搜索时,会检查当前关键字在不在黑名单中,如果在,则提示不能搜索。
总结:
CopyOnWriteArrayList使用写时复制的策略来保证list的一致性,而获取-修改-写入三步操作并不是原子性的,所以在增删改的过程中都是用了独占锁,来保证某个时间只有一个线程能对list数组进行修改。另外CopyOnWriteArrayList提供了弱一致性的迭代器,从而保证在获取迭代器后,其他线程对List的修改是不可见的,迭代器遍历的数组是一个快照。