在高并发的情况下,在循环中使用i++时往往会出现些问题。这是由于i++不具备原子性(读取i的值,加1,再写回主存,是3步操作)。为了避免这类问题,我们有三种处理方式:
- 在方法块上加入synchronized关键字,保证在同一时刻,只有一个线程可以执行某个方法或某个代码块,但是如果在读取较多而写入较少时程序效率低下。
- 使用一种 “程度较轻的 synchronized”,即在变量上加volatile修饰,然而volatile不好把控,使用volatile的代码往往比使用锁的代码更加容易出错。
- 使用autioInteger。引用了网上的一段代码:
10个线程执行累加100000次,执行结果如下:
多次执行,或者加大循环,AtomicIntegerd能保证结果始终是1000000,而普通变量和加上了volatile修饰的变量并不能。
AtomicIntegerd优点
1.乐观锁,性能较强,利用CPU自身的特性保证原子性,即CPU的指令集封装compare and swap两个操作为一个指令来保证原子性。
2.适合读多写少模式
但是缺点明显
1.自旋,消耗CPU性能,所以写的操作较多推荐synchronized
2.仅适合简单的运算,否则会产生ABA问题,自旋的时候,别的线程可能更改value,然后又改回来,此时需要加版本号解决,JDK提供了AtomicStampedReference和AtomicMarkableReference解决ABA问题,提供基本数据类型和引用数据类型版本号支持