java concurrent int_java并发编程--AtomicInteger

1.问题提出

先看下AtomicInteger的类属性和成员变量:

//setup to use Unsafe.compareAndSwapInt for updates

private static final Unsafe unsafe =Unsafe.getUnsafe();private static final longvalueOffset;static{try{

valueOffset=unsafe.objectFieldOffset

(AtomicInteger.class.getDeclaredField("value"));

}catch (Exception ex) { throw newError(ex); }

}private volatile int value;

可以看到:

1.AtomicInteger类使用Unsafe,直接操作内存 来保证 原子性。

2.还有个long类型的 valueOffset。并且在类加载时,初始化了值。

3.有一个用volatile修饰的成员变量 int 类型 value。

看到这,其中value明显就是AtomicInteger所包装的值,即我们用得到的值。但是valueOffset值代表的是什么呢? 还有这个unsafe是怎么操作的?

2.valueOffset

看其初始化的赋值方法,是unsafe的一个native方法:

public native long objectFieldOffset(Field var1);

objectFieldOffset方法,返回成员属性在内存中的地址相对于对象内存地址的偏移量  (来自百度)

那么对于每个对象来说,偏移量都是固定的,所以作为一个类变量。

那么对象的内存地址+偏移量 就可以知道成员变量value在内存中的具体地址了,此时我们就可以操作它了,此时java从“安全”变得“不安全”了。

3.关于unsafe

unsafe是一个用于直接操作内存的类,那么 我们通过AtomicInteger的方法来看下用法。

a、先看下自增自减 这种典型的非原子操作 AtomicInteger是如何做的。

/*** Atomically increments by one the current value.

*

*@returnthe previous value*/

public final intgetAndIncrement() {return unsafe.getAndAddInt(this, valueOffset, 1);

}/*** Atomically decrements by one the current value.

*

*@returnthe previous value*/

public final intgetAndDecrement() {return unsafe.getAndAddInt(this, valueOffset, -1);

}

先看下运行结果:

47c49010f56c19dc253bee99af3463b1.png

方法的返回值是老值,这个别用错了

这是我们看到了 unsafe的方法:

public final int getAndAddInt(Object var1, long var2, intvar4) {intvar5;do{

var5= this.getIntVolatile(var1, var2);

}while(!this.compareAndSwapInt(var1, var2, var5, var5 +var4));returnvar5;

}

Unsafe.getObjectVolatile():

获取所给对象的所给变量的值,使用volatile语义的load语义,会在实际获取这个值的时候从主存中加载,不会使用CPU缓存中的,总能确保获取到的是有效的值

compareAndSwapInt(var1, var2, var5, var5 +var4):

首先找出Object var1在内存中的位置p, 然后偏移var2个字节, 设p+var2处的这个int值为y,

如果y ==var5, 则执行赋值操作y = var5+var4, 返回true

如果y != var5, 则不执行赋值操作, 返回false

那个unsafe.getAndAddInt(Object var1,long var2,int var4)的代码我们就读懂了:

1.取到队形var1的偏移量var2下的成员变量的值,读取值后,作为期望值。

2. 在赋值操作的时候,先从内存中取到值和期望值比较,如果相等,则进行运算赋值操作,返回成功,结束。

3.否则,循环第一步。

其实就是 在unsafe中实现了CAS。

接着看AtomicInteger的其他方法

b.

/*** Gets the current value.

*

*@returnthe current value*/

public final intget() {returnvalue;

}/*** Sets to the given value.

*

*@paramnewValue the new value*/

public final void set(intnewValue) {

value=newValue;

}

最简单的get set 方法因为成员变量是volatile修饰,这样既可保证了内存的可见性。

c.

其余方法就不一一罗列,但是其基本原理皆为unsafe.compareAndSwapInt()的,总结老说就是利用了CAS来保证了原子性。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值