根据自己的理解将需要打包成原子操作的部分加锁
List<Object> arrayList = Collections.synchronizedList(new ArrayList<>());返回的list所带有的各种关键方法都被synchronized修饰。 类似于Vector StringBuffer HashTable 这样的类虽然安全了,但是频繁加锁导致的性能损耗无法让人接受,一般来说不推荐使用
CopyOnWrite是一种写时拷贝的容器,这是一种常见的编程方法。
核心思想: 当我们往⼀个容器添加元素的时候,不直接往当前容器添加,而是先将当前容器进行Copy,复制出⼀个新的容器,然后新的容器⾥添加元素, 添加完元素之后,再将原容器的引用指向新的容器。

当然这个办法也存在缺点: 1.数组很大时,效率很低 2.多个线程同时修改数据,也会产生问题。
但是在读多写少的场景下,效率还是很高的。
首先HashMap线程不安全 提供的Hashtable只是给关键方法加锁,线程安全但是不推荐使用
前景回顾: 咱们都知道,哈希表会产生哈希冲突问题。如果哈希表是用顺序表实现的,可以使用线性探测等方法来解决哈希冲突。但是这种方法效率低,而且效果也不好。所以一般来说哈希表是使用链表来实现的,也可以说是哈希桶,这也正是HashMap内部实现的逻辑。
前提: 哈希桶的实现方式中,每一个桶都是一个长链表。在多线程场景中,如果涉及到对内容的修改,我们应该关注线程安全问题。不过,如果修改操作针对的是不同的桶,其实根本不会有线程安全问题。只有涉及到两个线程的修改操作修改的是两个相邻的表结点时才会产生线程安全问题。
Hashtable的逻辑是对关键方法加锁,这样会产生很多问题:


1.读操作没必要加锁,但还是加锁了 2.修改操作只有修改的是同一个链表里面的结点才有可能会有线程安全问题,但是Hashtable是对操作加锁 3.扩容的时候,如果这个哈希表很大,会消耗很长时间,这段时间都处于阻塞状态
基于以上问题,ConcurrentHashMap都能很好地解决。
如何优化? 1.读操作没有加锁(但是使用了 volatile 保证从内存读取结果), 2.对写操作进⾏加锁. 加锁的⽅式仍然是是⽤ synchronized, 但是不是锁整个对象, 而是 “锁桶” (用每个链表的头结点作为锁对象), 大大降低了锁冲突的概率. (实际开发中,Hash表可能会很大,通的数量也会有很多,即使是多线程条件下,两个线程同时修改同一个链表中的值的可能也很小) 3.充分利⽤ CAS 特性. 比如 size 属性通过 CAS 来更新. 避免出现重量级锁的情况.也就是将size定义成原子类。(原来的话size的操作也和读写之间有阻塞) 4.扩容优化: 多线程协助扩容:发起扩容的主线程先建两倍长的新数组,其他读写线程发现扩容中会主动加入,分工转移不同桶的元素(比如你搬 1-5 号桶,我搬 6-10 号),避免单线程慢。 转移与兼容:转移完的桶会引导读写直接走新数组,也就是直接向新扩容后哈希表中写入数据;没转移完的桶正常操作,写线程还会顺手帮着转移。 收尾:所有桶转完后,数组引用切到新数组,更新扩容阈值。
本文围绕多线程场景下的集合安全与性能平衡问题,梳理了核心选型逻辑与优化思路:ArrayList 线程不安全,Collections.synchronizedList和 Hashtable 因全局锁导致性能瓶颈,而CopyOnWriteArrayList基于 “写时拷贝” 机制实现读操作无锁高效,适配读多写少场景(需注意大数据量拷贝损耗);ConcurrentHashMap则通过读操作 volatile 保证可见性、写操作锁单个桶、CAS 优化原子操作、多线程协助扩容等设计,彻底解决了 Hashtable 的锁冲突频繁、扩容低效等问题,成为多线程哈希表的首选。整体选型需结合读写比例与场景需求,优先规避全局锁方案,在保证线程安全的同时最大化并发效率。