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