线程不安全——Part-2

Collections部分

一般情况下,我们使用ArrayList、HashSet、HashMap是在方法中定义局部变量,此时由于堆栈封闭的特性,自然不会有线程安全问题。但是,当将其定义为静态域中,且未做线程安全措施时,极有可能会导致多线程并发错误。

说明

由于该三个集合是Java中最常见的、最重要的集合,此处仅分析说明是非线程安全的类。其详细内容我会另起手记再做说明!!

ArrayList

弄个例子:(还是之前的框架)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
@Slf4j
@NotThreadSafe
public class ArrayListExample {

public static int clientTotal = 5000;
public static int threadTotal = 200;

private static List<Integer> list = new ArrayList<>();

public static void main(String[] args) throws Exception {
ExecutorService executorService = Executors.newCachedThreadPool();
final Semaphore semaphore = new Semaphore(threadTotal);
final CountDownLatch countDownLatch = new CountDownLatch(clientTotal);
for (int i = 0; i < clientTotal; i++) {
final int count = i;
executorService.execute(() -> {
try {
semaphore.acquire();
update(count);
semaphore.release();
} catch (Exception e) {
log.error("exception", e);
}
countDownLatch.countDown();
});
}
countDownLatch.await();
executorService.shutdown();
log.info("size:{}", list.size());
}
private static void update(int i) { list.add(i); }
}

运行结果:

1
13:31:39.296 [main] INFO com.mmall.concurrency.commonUnsafe.ArrayListExample - size:4986

显而易见,是非线程安全的。

HashSet

同理,HashSet同样进行测试,结果表明同样是非线程安全的!

HashMap

同理,HashMap同样进行测试,结果表明同样是非线程安全的!

线程不安全的写法

先检查再执行

1
2
3
4
if (aaaa)
{
bbbbbbbbb;
}

这个较易解释,在之前说AtomicXXX时说过:
在多线程并发时,可能多个线程执行到if语句的判断,且同时符合,然后分别作出修改。即该操作的原子性不能得到保证!故当有多线程并发问题时,考虑清楚,加锁进行处理。

SupriseMF wechat
欢迎关注微信订阅号【星球码】,分享学习编程奇淫巧技~
喜欢就支持我呀(*^∇^*)~

热评文章