list实现线程安全
线程不安全的展示:
-
爆出异常:
Exception in thread "11" java.util.ConcurrentModificationException
-
代码
public class CopyOnWriteArrayListTest { public static void main(String[] args) { // 1.演示并发修改失败,演示不安全的集合类 List<String> list = new ArrayList<>(); for (int i = 0; i < 20; i++) { new Thread(()->{ list.add(UUID.randomUUID().toString().substring(0,5)); // 必须打印调用出来 System.out.println(list); },String.valueOf(i)).start(); } } }
-
分析:在添加数据的时候,会覆盖我们前一个线程添加的内容。
-
举例说明:线程A发现下标11没人为空,它打算插入数据,结果被操作系统挂起了,线程B发现下标11位置为空,于是乎添加一条数据,然后线程A获得执行,也会添加到下标11位置,导致并发修改异常!
解决多线程集合安全办法(1)
使用安全集合 Vector
代码
List<String> list2 = new Vector<>();
for (int i = 0; i < 200; i++) {
new Thread(() -> {
list2.add(UUID.randomUUID().toString().substring(0, 5));
// 必须打印调用出来
System.out.println(list2);
}, String.valueOf(i)).start();
}
原理:底层的每个可能并发出错方法都用synchronized修饰
解决多线程集合安全办法(2)
使用工具类集合框架Collections.synchronizedList
代码
List<Object> list3 = Collections.synchronizedList(new ArrayList<>());
for (int i = 0; i < 200; i++) {
new Thread(() -> {
list3.add(UUID.randomUUID().toString().substring(0, 5));
// 必须打印调用出来
System.out.println(list3);
}, String.valueOf(i)).start();
}
原理:类似与上一个
解决多线程集合安全办法(3)
使用juc下的CopyOnWriteArrayList 使用 reentrantLock锁和复制数组
代码
List<Object> list4 = new CopyOnWriteArrayList<>();
for (int i = 0; i < 200; i++) {
new Thread(() -> {
list4.add(UUID.randomUUID().toString().substring(0, 5));
// 必须打印调用出来
System.out.println(list4);
}, String.valueOf(i)).start();
}
原理:可能并发的方法用lock类取代synchronized,写时复制原理?好处是什么?
- 我们用一个数组保存数据
- 我们修改时,复制出一份数据用来修改,这样读的线程就可以不受写锁的影响而阻塞。
- 修改完成时,把数组指针指向我们修改完成的这个数组。
- 保证了安全性。