当前位置: 代码迷 >> 综合 >> JDK源码研究(六):AtomicInteger
  详细解决方案

JDK源码研究(六):AtomicInteger

热度:16   发布时间:2023-10-14 02:00:21.0

JDK源码研究(六):AtomicInteger

AtomicInteger继承了Number类,Integer也继承了该类,主要定义了一些转换成其他数值型类的方法,如Double、Long、Float等。其内部属性比较少,第一个Unsafe类是rt.jar包下的一个类,这里主要用于获取其内部属性value的内存偏移值和做一些CAS操作。

unsafe用的是单例模式,且只有BootstrapClassLoader类加载器才能获取该单例。

JDK源码研究(六):AtomicInteger

获取Unsafe类的实例的时候会判断调用类的类加载器是否为BootstrapClassLoader类加载器,如果不是则会抛出一个SecurityException异常。因为该类可以对JVM的内存进行直接操作,使用不当可能导致JVM崩溃,所以限制使用吧。当然,也可以反射强制获取该单例。

valueOffset记录了value属性相对于AtomicInteger实例内存地址的偏移值。可以看到静态代码块中,就是对valueOffset的获取。

public native long objectFieldOffset(Field var1); 

可以获取非静态属性对于该类实例内存地址的偏移值。在这里获取了value属性的相对于AtomicInteger实例的偏移值,该属性会在后面CAS操作中使用到。

再来看最后一个属性value,使用了volatile修饰,会使该属性再使用时会强制从主内存中获取具体值,而不是线程的副本内存中获取,而且会防止对该属性操作的指令重排序。

JDK源码研究(六):AtomicInteger

再来看我们常用到的getAndIncrement方法,非常简单,就调用了unsafe的getAndAddInt方法,然后将当前实例,value的偏移值(valueOffset静态属性), 和 1作为参数传入。

JDK源码研究(六):AtomicInteger

其内部实现是用过一个循环,获取当前内存中value最新的值,并通过判断value是不是这个值,如果是则将原有值 加上 添加的值替换原有值,如果失败则继续循环。最后返回原有值。用这种CAS轻量级操作来代替锁。

其他方法都是大同小异的CAS操作,这里就不多阐述了。