CopyOnWriteArraySet

Set不安全

HashSet底层使用的是什么?

我们去查看源码,点击进去一看发现

其实底层就是使用了HashMap去实现的。

为什么Set不安全?

先给出代码

arduino 复制代码
public class TestSet {
    public static void main(String[] args) {
        HashSet<String> set = new HashSet<>();
        for (int i = 0; i < 20; i++) {
            int finalI = i;
            new Thread(() -> {
                set.add(String.valueOf(finalI));
                System.out.println( set);
            }, String.valueOf(i)).start();
        }
    }
}

发现在多线程下会出现ConcurrentModificationException问题。

原因:

HashSet 是基于 HashMap 实现的,它本身并没有提供内置的线程安全机制。当多个线程同时对 HashSet 进行修改时(如执行 add() 操作),可能会导致 数据丢失 、数据不一致 ,甚至出现 ConcurrentModificationException 异常。

解决方案

1.显示加锁

ini 复制代码
Set<String> set = new HashSet<>();
Object lock = new Object();

for (int i = 0; i < 20; i++) {
    int finalI = i;
    new Thread(() -> {
        synchronized (lock) {
            set.add(String.valueOf(finalI));
            System.out.println(set);
        }
    }, String.valueOf(i)).start();
}

2. 使用 Collections.synchronizedSet()

vbnet 复制代码
Set<String> set = Collections.synchronizedSet(new HashSet<>());

这样,所有对 set 的操作都将通过同步进行,从而避免了线程安全问题。然而,使用这种方式时需要注意,如果你要迭代 set,仍然需要手动加锁,因为 synchronizedSet 仅保证基本的操作是同步的。

arduino 复制代码
synchronized(set) {
    for (String item : set) {
        // 迭代操作
    }
}

3. 使用 CopyOnWriteArraySet

CopyOnWriteArraySet 是一个线程安全的 Set 实现,底层使用 CopyOnWriteArrayList。它适用于 读多写少 的场景,因为每次写操作都需要复制底层数据结构。但它在写操作频繁的场景下性能较差。

vbnet 复制代码
Set<String> set = new CopyOnWriteArraySet<>();

CopyOnWriteArraySet原理和CopyOnWriteArrayList类似;

相关推荐
GISer_Jing2 小时前
营销活动低代码前后台方案
后端
IT_陈寒3 小时前
React项目实战经验分享:如何避免useEffect闭包陷阱导致的陈旧状态问题?
前端·人工智能·后端
Maynor9963 小时前
免费 Cloudflare 只有 10 个 D1?满了之后的「穷鬼打法」:表前缀复用同一个库
数据库·后端·云计算·cloudflare
沙蒿同学11 小时前
不引 Ghostscript:我用纯 Go 给 PDF 做了一场「压缩手术」
前端·后端·github
前进的李工13 小时前
飞书企业知识库设计+后端高频八股
数据库·redis·后端·mysql·性能优化·飞书·rag
金銀銅鐵15 小时前
[Java] 展示增删元素时 LinkedList 的内部变化
java·后端·ai编程
武子康16 小时前
Vercel Cache Reason:相同 MISS,怎样决定下一步查什么
人工智能·后端·agent
杨文说AI与数字化16 小时前
把模型依赖做成可替换的组件:三层适配 + 一套回归评估
后端
IT_陈寒16 小时前
Vue的这个响应式陷阱我居然现在才发现
前端·人工智能·后端
WL学习笔记17 小时前
使用string类
c++·后端·string类