4-1 原子变量操作类
这种类的作用其实就是
在线程之中调用这个类,向它的构造函数传递一个value(注意,这个value是一个Long类型的值) 然后用这个类的方法对这个值进行原子性的递增递减操作。
以AtomicLong类来详细分析源码
(好像书中用的版本的代码和我现在使用的又不一样了,我现在用书中的代码)
构造函数为:
public AtomicLong(long initialValue) {
this.value = initialValue;
}
public AtomicLong() {
}
以下是AtomicLong类中用到的内部变量以及它们的用处
public class AtomicLong extends Number implements Serializable {
private static final long serialVersionUID = 1927816293512124184L;
//实际要操作的值value
private volatile long value;
//获取Unsafe实例
private static final Unsafe unsafe = Unsafe.getUnsafe();
//存放value的偏移量
private static final long VALUE;
//判断JVM是不是支持Long类型无锁CAS(不懂)
static final boolean VM_SUPPORTS_LONG_CAS = VMSupportsCS8();
private static native boolean VMSupportsCS8();
static {
try{
//获取value的偏移量
VALUE = unsafe.objectFieldOffset(AtomicLong.class, "value");
}catch(Exception ex){throw new Error(ex);}
}
//构造函数
public AtomicLong(long initialValue) {
this.value = initialValue;
}
public AtomicLong() {
}
1.递增和递减操作代码
最关键的是类中的原子性操作的实现(它们的作用是对value实行原子性的操作)
它们都大同小异:
public final long getAndIncrement() {
return unsafe.getAndAddLong(this, VALUE, 1L);
}
public final long incrementAndGet() {
return unsafe.getAndAddLong(this, VALUE, 1L) + 1L;
}
public final long decrementAndGet() {
return unsafe.getAndAddLong(this, VALUE, -1L) - 1L;
}
它们都是调用unsafe的getAndAddLong,这个函数是个原子性操作,这里第一个参数是 AtomicLong 实例的引用 第二个参数是 value 变量AtomicLong 中的偏移值,第三个参数是要设置的第二个变量的值。
Unsafe中的getAndAddLong代码为:
public final long getAndAddLong(Object o, long offset, long delta) {
long v;
do {
v = this.getLongVolatile(o, offset);
} while(!this.weakCompareAndSetLong(o, offset, v, v + delta));
return v;
}
解释:这个方法被上面的方法调用,结合起来的意识就是拿到value的当前值,然后在工作内存中对其进行+1操作。
2. boolean CompareAndSet方法
这是AtomicLong中一系列方法
public final boolean CompareAndSet(long expect, long update) {
return unsafe.compareAndSwapLong(this, VALUE, expect, update);
}
它还是调用的是Unsafe中的compareAndSwapLong方法:如果原子变量中的value等于expect,则用update更新之,并返回true。否则返回false。
3.例子
加深理解
import java.util.concurrent.atomic.AtomicLong;
public class AtomicTest {
//AtomicLong数组
private static AtomicLong atomicLong=new AtomicLong();
//数据源头
private static Integer[] arrayone=new Integer[]{0,1,2,3,0,5,6,0,56,0};
private static Integer[] arraytwo=new Integer[]{10,1,2,3,0,5,6,0,56,0};
public static void main(String[] args) throws InterruptedException {
//线程1统计arrayone数组中0的个数
Thread threadone=new Thread(new Runnable() {
@Override
public void run() {
int size=arrayone.length;
for(int i=0;i<size;i++)
{
if(arrayone[i]==0)
atomicLong.incrementAndGet();
}
}
});
Thread threadtwo=new Thread(new Runnable() {
@Override
public void run() {
int size=arraytwo.length;
for(int i=0;i<size;i++)
{
if(arraytwo[i]==0)
atomicLong.incrementAndGet();
}
}
});
//启动子线程
threadone.start();
threadtwo.start();
//等待线程执行完毕
threadone.join();
threadtwo.join();
System.out.println("count 0:"+atomicLong.get());
}
}
输出为:
这代表两个线程利用的atomic对象进行的操作是原子性的,没有发生混乱