AtomicInteger源码分析
来源:互联网 发布:类似炫浪网络社区 编辑:程序博客网 时间:2024/05/17 02:41
要解决什么问题
最常需要解决的问题是i++ 这个语义在多线程中是不安全的。虽然从语法上看上去是一个操作,实际上分为了三步。取出i的值,i+1,将i+1的计算结果赋值给i。假设i的初始值为5,一种不安全的情况如下:
也就是说两个线程并发执行i++操作,所得的结果都是6 !而我们期望应该是一个是6,一个是7。如果这个用于数据库主键的生成,这将导致严重的主键冲突。
如何解决
AtomicInteger类
// setup to use Unsafe.compareAndSwapInt for updatesprivate static final Unsafe unsafe = Unsafe.getUnsafe();private static final long valueOffset;static { try { valueOffset = unsafe.objectFieldOffset (AtomicInteger.class.getDeclaredField("value")); } catch (Exception ex) { throw new Error(ex); }}private volatile int value;public final int incrementAndGet() { return unsafe.getAndAddInt(this, valueOffset, 1) + 1; }
value:用volatile修饰使得变量对所有线程可见,代表实际值,AtomicInteger.get()就是返回这个的值。
valueOffset:value的偏移地址
incrementAndGet():这是也就是我们常用的保证原子操作递增方法,它实际上调用了unsafe.getAndAddInt()
Unsafe类并不能直接查看到源码,只能通过反编译来看。
Unsafe类
public final native boolean compareAndSwapInt(Object object, long valueOffset, int expected, int update);public final int getAndAddInt(Object object, long valueOffset, int increament) { int expected; do { expected = this.getIntVolatile(object, valueOffset); } while(!this.compareAndSwapInt(object, valueOffset, expected, expected + increament)); return expected;}
先看看compareAndSwapInt方法,方法用native修饰,表示是一个本地方法,调用的是CAS指令执行,这是整个过程是一个原子操作。功能是如果地址(由object和valueOffset共同确定)中的值与expected相同,则设置改地址的值为update,并返回true,否则不更新且返回false。
再看看getAndAddInt(),在这个方法中调用了this.getIntVolatile(object, valueOffset),表示获取地址中的值,那么整个getAndAddInt()方法的语义是:
1.获取到对象中存储value地址的值
2.然后再回去比较是否相等,相等则更新,否则从1开始重试直到成功。
为什么AtomicInteger操作并不会出现线程问题:当两个线程同时进入do-while循环中后,只有第一个线程能执行更新操作成功并退出循环,第二个线程试图执行赋值操作因为地址中的值不一致而不会更新,只能重新执行循环,重新执行循环获得到的是最新的value值,所以此处并不会出现线程问题。
该类的中其它方法与本文类似,故不重复分析。
注:本文源码为JDK1.8
- AtomicInteger源码分析
- Java AtomicInteger源码分析
- AtomicInteger源码分析
- AtomicInteger源码分析
- AtomicInteger源码分析
- JDK源码分析-AtomicInteger
- JDK源码分析-AtomicInteger
- JDK AtomicInteger 源码分析
- JDK AtomicInteger 源码分析
- AtomicInteger 源码分析
- AtomicInteger源码分析
- AtomicInteger源码分析
- Java并发-AtomicInteger源码分析
- Java并发之AtomicInteger源码分析
- 【Java8源码分析】并发包-AtomicInteger
- AtomicInteger源码
- AtomicInteger源码
- JUC源码分析1-原子变量-AtomicInteger/AtomicBoolean/AtomicLong/AtomicReference
- 输入两个整数 n 和 m,从数列1,2,3.......n 中 随意取几个数, 使其和等于 m ,要求将其中所有的可能组合出来---经典数据结构第21道
- leetcode 344. Reverse String
- 管理城市坐标的简单C++程序
- fun
- PAT 1009
- AtomicInteger源码分析
- 新闻发布项目——接口类(UserDao)
- 【转载】Android 使用开源库StickyGridHeaders来实现带sections和headers的GridView显示本地图片效果
- 根据ID从主题中获取值
- AndroidStudio快捷键
- 绪论(3)--周志华机器学习学习笔记与课后习题
- Julia: 自制的Julia代码排版工具CodeBeautify
- sizeof计算对象所占内存的大小详解
- python对象引用引起的问题