AtomicInteger
来源:互联网 发布:阿里云新手礼包在哪里 编辑:程序博客网 时间:2024/06/05 04:36
AtomicInteger 是一个支持原子操作的 Integer 类,就是保证对AtomicInteger类型变量的增加和减少操作是原子性的,不会出现多个线程下的数据不一致问题。通常情况下,在Java里面,++i或者--i不是线程安全的,这里面有三个独立的操作:获取变量当前值,为该值+1/-1,然后写回新的值。在没有额外资源可以利用的情况下,只能使用加锁才能保证读-改-写这三个操作时“原子性”的。
先看AtomicInteger中的几个方法:
int addAndGet(int delta)
以原子方式将给定值与当前值相加。实际上就是等于线程安全版本的i=i+delta操作。
boolean compareAndSet(int expect, int update)
如果当前值 ==预期值,则以原子方式将该值设置为给定的更新值。如果成功就返回true,否则返 回false,并且不修改原值。
int decrementAndGet()
以原子方式将当前值减 1。相当于线程安全版本的--i操作。
int get()
获取当前值。
int getAndAdd(intdelta)
以原子方式将给定值与当前值相加。相当于线程安全版本的t=i;i+=delta;returnt;操作。
int getAndDecrement()
以原子方式将当前值减 1。相当于线程安全版本的i--操作。
int getAndIncrement()
以原子方式将当前值加 1。相当于线程安全版本的i++操作。
int getAndSet(intnewValue)
以原子方式设置为给定值,并返回旧值。相当于线程安全版本的t=i;i=newValue;returnt;操作。
int incrementAndGet()
以原子方式将当前值加 1。相当于线程安全版本的++i操作。
再看源码:
<span style="font-size:18px;">package java.util.concurrent.atomic;import sun.misc.Unsafe;public class AtomicInteger extends Number implements java.io.Serializable { private static final long serialVersionUID = 6214790243416807050L; // setup to use Unsafe.compareAndSwapInt for updates private 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 AtomicInteger(int initialValue) { value = initialValue; } public AtomicInteger() { } public final int get() { return value; } public final void set(int newValue) { value = newValue; } public final void lazySet(int newValue) { unsafe.putOrderedInt(this, valueOffset, newValue); } //以原子方式设置为给定值,并返回旧值。 public final int getAndSet(int newValue) { for (;;) { int current = get(); if (compareAndSet(current, newValue)) return current; } } //如果当前值 ==预期值,则以原子方式将该值设置为给定的更新值。如果成功就返回,否则返回,并且不修改原值。public final boolean compareAndSet(int expect, int update) {return unsafe.compareAndSwapInt(this, valueOffset, expect, update); } public final boolean weakCompareAndSet(int expect, int update) {return unsafe.compareAndSwapInt(this, valueOffset, expect, update); } //以原子方式将当前值加1。相当于线程安全版本的i++操作。 public final int getAndIncrement() { for (;;) { int current = get(); int next = current + 1; if (compareAndSet(current, next)) return current; } } //以原子方式将当前值减 1相当于线程安全版本的i--操作。 public final int getAndDecrement() { for (;;) { int current = get(); int next = current - 1; if (compareAndSet(current, next)) return current; } } //以原子方式将给定值与当前值相加。相当于线程安全版本的操作。 public final int getAndAdd(int delta) { for (;;) { int current = get(); int next = current + delta; if (compareAndSet(current, next)) return current; } } //以原子方式将当前值加 1相当于线程安全版本的++i操作。 public final int incrementAndGet() { for (;;) { int current = get(); int next = current + 1; if (compareAndSet(current, next)) return next; } } //以原子方式将当前值减 1。相当于线程安全版本的--i操作。 public final int decrementAndGet() { for (;;) { int current = get(); int next = current - 1; if (compareAndSet(current, next)) return next; } } //以原子方式将给定值与当前值相加。实际上就是等于线程安全版本的i=i+delta操作 public final int addAndGet(int delta) { for (;;) { int current = get(); int next = current + delta; if (compareAndSet(current, next)) return next; } }} </span>
通过源码可以发现,AtomicInteger并没有使用Synchronized关键字实现原子性,几乎所有的数据更新都用到了compareAndSet(int expect, int update)这个方法。那么就不难看出AtomicInteger这个类的最核心的函数就是compareAndSet(int expect, int update)。
那么compareAndSet(int expect, int update)是干什么的呢????
我们以getAndIncrement()方法为例,它的源码如下:
<span style="font-size:18px;">public final int getAndIncrement() { for (;;) { int current = get(); int next = current + 1; if (compareAndSet(current, next)) return current; } }</span>
单看这段 代码 很难保证原子性, 因为根本没有更新value 的操作
重点在于compareAndSet() 函数
public final boolean compareAndSet(int expect,int update)
- 如果当前值
==
预期值,则以原子方式将 当前值 设置为给定的更新值。 - 参数:
expect
- 预期值update
- 新值- 返回:
- 如果成功,则返回 true。返回 False 指示实际值与预期值不相等。
该函数 只有两个参数,可操作的确实三个值 ,即 value ,expect, update. 他使用了 由硬件保证其原子性的指令 CAS (compare and swap)。
compareAndSet 函数保证了 比较,赋值这两步操作可以通过一个原子操作完成。
然后看整个函数, 所有代码被放到了一个循环里面, 如果compareAndSet()执行失败,则说明 在int current = get(); 后,其他线程对value进行了更新, 于是就循环一次,重新获取当前值,直到compareAndSet()执行成功为止。
这里需要注意的是AtomicInteger所利用的是基于冲突检测的乐观并发策略(CAS自旋锁)。 所以这种乐观在线程数目非常多的情况下,失败的概率会指数型增加。
- AtomicInteger
- AtomicInteger
- AtomicInteger
- AtomicInteger
- AtomicInteger
- AtomicInteger
- AtomicInteger
- AtomicInteger
- AtomicInteger
- AtomicInteger
- AtomicInteger
- AtomicInteger
- AtomicInteger
- AtomicInteger
- AtomicInteger
- AtomicInteger
- AtomicInteger
- AtomicInteger
- JQuery调用iframe子页面函数/对象的方法
- Struts2 集成 sitemesh配置
- Android中无返回值的页面跳转
- poj--3278
- ArcGIS教程:了解坡度
- AtomicInteger
- 初学AsyncTask
- eclipse最有用快捷键整理 by 戎码一生
- 通过Smart HTTP提供代码下载/上传服务
- Html5添加audio音频播放器插件教程
- Android:Intent
- Python学习笔记(1)
- C# 鼠标点击任务栏图标软件还原或最小化
- Anroid 数据持久化方案