使用countDownLatch导致的线程安全问题,线程不安全的List-ArrayList,线程安全的List-CopyOnWriteArrayList

示例代码

java 复制代码
package com.example.demo.service;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class UnSafeCDTest {

    ExecutorService executorService = Executors.newFixedThreadPool(5);

    public static void main(String[] args) throws InterruptedException {
        for(int i = 0; i < 20; i++){
            UnSafeCDTest unSafeCDTest = new UnSafeCDTest();
            unSafeCDTest.test();
        }

    }


    public void test() throws InterruptedException {
        List<String> list = new ArrayList<>();
      //  List<String> list = new CopyOnWriteArrayList<>();
        CountDownLatch countDownLatch = new CountDownLatch(5);
        for (int i = 0; i < 5; i++) {
            executorService.submit(() -> {
                // TODO
                list.add("1" );
                // TODO
                // cd
                countDownLatch.countDown();

            });
        }
        countDownLatch.await();
        System.out.println( list.size());

    }
}

输出结果

image.png

可以看到有一个结果为4;

修改ArrayList为线程安全的List,CopyOnWriteArrayList;

验证结果

image.png

CopyOnWriteArrayList为什么是线程安全的

查看源码可以看到通过了加锁实现了线程安全

复制代码
/**
     * Appends the specified element to the end of this list.
     *
     * @param e element to be appended to this list
     * @return {@code true} (as specified by {@link Collection#add})
     */
    public boolean add(E e) {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            Object[] elements = getArray();
            int len = elements.length;
            Object[] newElements = Arrays.copyOf(elements, len + 1);
            newElements[len] = e;
            setArray(newElements);
            return true;
        } finally {
            lock.unlock();
        }
    }
相关推荐
Bs_MoneyMagnet40 分钟前
基于springboot+vue的滑雪场票务与装备租赁系统的设计与实现 源码+文档
java·vue.js·spring boot·后端·spring·毕业设计·计算机毕业设计
野生技术架构师6 小时前
2026 Java 面试全套总结,八股 + 场景 + AI 相关面试考点
java·人工智能·面试
香吧香6 小时前
java服务异常日志只打印异常类型,没有堆栈定位分析
java·jvm·异常
qq_2518364577 小时前
AI 疾病自查功能SpringbootAI项目实战 · 技术实现文档
java·ai·ai编程
逆境不可逃8 小时前
Pi Agent 学习笔记:对话太长以后,如何压缩上下文
java
MetaLite8 小时前
JDK 8~26 核心特性一览:从 Stream 到 Scoped Values
java
wno7048 小时前
Spring Boot WebFlux增删改查
java·spring boot·后端
君顾18 小时前
上海24小时自助健身房系统开发实战指南:从架构设计到落地部署
java·开发语言·健身房
香菜TTT9 小时前
大模型上下文协议(MCP):AI 应用的“USB-C”接口技术
开发语言·人工智能·经验分享
aramae9 小时前
模拟实现strlen()函数 (C语言)
c语言·开发语言·后端