示例代码
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();
}
}