深入学习java源码之AtomicInteger.get()与AtomicInteger.incrementAndGet()
为什么需要AtomicInteger原子操作类?
对于Java中的运算操作,例如自增或自减,若没有进行额外的同步操作,在多线程环境下就是线程不安全的。num++解析为num=num+1,明显,这个操作不具备原子性,多线程并发共享这个变量时必然会出现问题。
这里运行了20个线程,每个线程对count变量进行1000此自增操作,如果上面这段代码能够正常并发的话,最后的结果应该是20000才对,但实际结果却发现每次运行的结果都不相同,都是一个小于20000的数字。
把上面的代码改造成AtomicInteger原子类型
结果每次都输出20000,程序输出了正确的结果,这都归功于AtomicInteger.incrementAndGet()方法的原子性。
多线程
同步:多线程并发访问共享数据时,保证共享数据再同一时刻只被一个或一些线程使用。
我们知道,阻塞同步和非阻塞同步都是实现线程安全的两个保障手段,非阻塞同步对于阻塞同步而言主要解决了阻塞同步中线程阻塞和唤醒带来的性能问题,那什么叫做非阻塞同步呢?在并发环境下,某个线程对共享变量先进行操作,如果没有其他线程争用共享数据那操作就成功;如果存在数据的争用冲突,那就才去补偿措施,比如不断的重试机制,直到成功为止,因为这种乐观的并发策略不需要把线程挂起,也就把这种同步操作称为非阻塞同步(操作和冲突检测具备原子性)。在硬件指令集的发展驱动下,使得 "操作和冲突检测" 这种看起来需要多次操作的行为只需要一条处理器指令便可以完成,这些指令中就包括非常著名的CAS指令(Compare-And-Swap比较并交换)。
incrementAndGet()方法在一个无限循环体内,不断尝试将一个比当前值大1的新值赋给自己,如果失败则说明在执行"获取-设置"操作的时已经被其它线程修改过了,于是便再次进入循环下一次操作,直到成功为止。这个便是AtomicInteger原子性的"诀窍"了,继续进源码看它的compareAndSet方法:
java源码
一个AtomicInteger
用于诸如原子增量计数器的应用程序中,不能用作Integer
的替代品 。 但是,这个类确实扩展了Number
以允许通过处理基于数字类的工具和实用程序的统一访问。
Modifier and Type | Method and Description |
| 使用将给定函数应用于当前值和给定值的结果原子更新当前值,返回更新后的值。 |
| 将给定的值原子地添加到当前值。 |
| 如果当前值 |
| 原子减1当前值。 |
| 返回此值 |
| 返回此值 |
| 获取当前值。 |
| 使用给定函数应用给当前值和给定值的结果原子更新当前值,返回上一个值。 |
| 将给定的值原子地添加到当前值。 |
| 原子减1当前值。 |
| 原子上增加一个当前值。 |
| 将原子设置为给定值并返回旧值。 |
| 用应用给定函数的结果原子更新当前值,返回上一个值。 |
| 原子上增加一个当前值。 |
| 将 |
| 最终设定为给定值。 |
| 返回此值 |
| 设置为给定值。 |
| 返回当前值的String表示形式。 |
| 使用给定函数的结果原子更新当前值,返回更新的值。 |
| 如果当前值 |
Modifier and Type | Method and Description |
| 返回指定号码作为值 |
| 返回指定数字的值为 |
| 返回指定数字的值为 |
| 返回指定号码作为值 |
| 返回指定数字的值为 |
| 返回指定号码作为值 |