Java concurrency之AtomicLong原子类_动力节点Java学院整理
AtomicLong介绍和函数列表
AtomicLong是作用是对长整形进行原子操作。
在32位操作系统中,64位的long和double变量由于会被JVM当作两个分离的32位来进行操作,所以不具有原子性。而使用AtomicLong能让long的操作保持原子型。
AtomicLong函数列表
//构造函数 AtomicLong() //创建值为initialValue的AtomicLong对象 AtomicLong(longinitialValue) //以原子方式设置当前值为newValue。 finalvoidset(longnewValue) //获取当前值 finallongget() //以原子方式将当前值减1,并返回减1后的值。等价于“--num” finallongdecrementAndGet() //以原子方式将当前值减1,并返回减1前的值。等价于“num--” finallonggetAndDecrement() //以原子方式将当前值加1,并返回加1后的值。等价于“++num” finallongincrementAndGet() //以原子方式将当前值加1,并返回加1前的值。等价于“num++” finallonggetAndIncrement() //以原子方式将delta与当前值相加,并返回相加后的值。 finallongaddAndGet(longdelta) //以原子方式将delta添加到当前值,并返回相加前的值。 finallonggetAndAdd(longdelta) //如果当前值==expect,则以原子方式将该值设置为update。成功返回true,否则返回false,并且不修改原值。 finalbooleancompareAndSet(longexpect,longupdate) //以原子方式设置当前值为newValue,并返回旧值。 finallonggetAndSet(longnewValue) //返回当前值对应的int值 intintValue() //获取当前值对应的long值 longlongValue() //以float形式返回当前值 floatfloatValue() //以double形式返回当前值 doubledoubleValue() //最后设置为给定值。延时设置变量值,这个等价于set()方法,但是由于字段是volatile类型的,因此次字段的修改会比普通字段(非volatile字段)有稍微的性能延时(尽管可以忽略),所以如果不是想立即读取设置的新值,允许在“后台”修改值,那么此方法就很有用。如果还是难以理解,这里就类似于启动一个后台线程如执行修改新值的任务,原线程就不等待修改结果立即返回(这种解释其实是不正确的,但是可以这么理解)。 finalvoidlazySet(longnewValue) //如果当前值==预期值,则以原子方式将该设置为给定的更新值。JSR规范中说:以原子方式读取和有条件地写入变量但不创建任何happen-before排序,因此不提供与除weakCompareAndSet目标外任何变量以前或后续读取或写入操作有关的任何保证。大意就是说调用weakCompareAndSet时并不能保证不存在happen-before的发生(也就是可能存在指令重排序导致此操作失败)。但是从Java源码来看,其实此方法并没有实现JSR规范的要求,最后效果和compareAndSet是等效的,都调用了unsafe.compareAndSwapInt()完成操作。 finalbooleanweakCompareAndSet(longexpect,longupdate)
AtomicLong源码分析(基于JDK1.7.0_40)
AtomicLong的完整源码
/*
*ORACLEPROPRIETARY/CONFIDENTIAL.Useissubjecttolicenseterms.
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
/*
*
*
*
*
*
*WrittenbyDougLeawithassistancefrommembersofJCPJSR-
*ExpertGroupandreleasedtothepublicdomain,asexplainedat
*http://creativecommons.org/publicdomain/zero/./
*/
packagejava.util.concurrent.atomic;
importsun.misc.Unsafe;
/**
*A{@codelong}valuethatmaybeupdatedatomically.Seethe
*{@linkjava.util.concurrent.atomic}packagespecificationfor
*descriptionofthepropertiesofatomicvariables.An
*{@codeAtomicLong}isusedinapplicationssuchasatomically
*incrementedsequencenumbers,andcannotbeusedasareplacement
*fora{@linkjava.lang.Long}.However,thisclassdoesextend
*{@codeNumber}toallowuniformaccessbytoolsandutilitiesthat
*dealwithnumerically-basedclasses.
*
*@since.
*@authorDougLea
*/
publicclassAtomicLongextendsNumberimplementsjava.io.Serializable{
privatestaticfinallongserialVersionUID=L;
//setuptouseUnsafe.compareAndSwapLongforupdates
privatestaticfinalUnsafeunsafe=Unsafe.getUnsafe();
privatestaticfinallongvalueOffset;
/**
*RecordswhethertheunderlyingJVMsupportslockless
*compareAndSwapforlongs.WhiletheUnsafe.compareAndSwapLong
*methodworksineithercase,someconstructionsshouldbe
*handledatJavaleveltoavoidlockinguser-visiblelocks.
*/
staticfinalbooleanVM_SUPPORTS_LONG_CAS=VMSupportsCS();
/**
*ReturnswhetherunderlyingJVMsupportslocklessCompareAndSet
*forlongs.CalledonlyonceandcachedinVM_SUPPORTS_LONG_CAS.
*/
privatestaticnativebooleanVMSupportsCS();
static{
try{
valueOffset=unsafe.objectFieldOffset
(AtomicLong.class.getDeclaredField("value"));
}catch(Exceptionex){thrownewError(ex);}
}
privatevolatilelongvalue;
/**
*CreatesanewAtomicLongwiththegiveninitialvalue.
*
*@paraminitialValuetheinitialvalue
*/
publicAtomicLong(longinitialValue){
value=initialValue;
}
/**
*CreatesanewAtomicLongwithinitialvalue{@code}.
*/
publicAtomicLong(){
}
/**
*Getsthecurrentvalue.
*
*@returnthecurrentvalue
*/
publicfinallongget(){
returnvalue;
}
/**
*Setstothegivenvalue.
*
*@paramnewValuethenewvalue
*/
publicfinalvoidset(longnewValue){
value=newValue;
}
/**
*Eventuallysetstothegivenvalue.
*
*@paramnewValuethenewvalue
*@since1.6
*/
publicfinalvoidlazySet(longnewValue){
unsafe.putOrderedLong(this,valueOffset,newValue);
}
/**
*Atomicallysetstothegivenvalueandreturnstheoldvalue.
*
*@paramnewValuethenewvalue
*@returnthepreviousvalue
*/
publicfinallonggetAndSet(longnewValue){
while(true){
longcurrent=get();
if(compareAndSet(current,newValue))
returncurrent;
}
}
/**
*Atomicallysetsthevaluetothegivenupdatedvalue
*ifthecurrentvalue{@code==}theexpectedvalue.
*
*@paramexpecttheexpectedvalue
*@paramupdatethenewvalue
*@returntrueifsuccessful.Falsereturnindicatesthat
*theactualvaluewasnotequaltotheexpectedvalue.
*/
publicfinalbooleancompareAndSet(longexpect,longupdate){
returnunsafe.compareAndSwapLong(this,valueOffset,expect,update);
}
/**
*Atomicallysetsthevaluetothegivenupdatedvalue
*ifthecurrentvalue{@code==}theexpectedvalue.
*
*Mayfailspuriously
*anddoesnotprovideorderingguarantees,soisonlyrarelyan
*appropriatealternativeto{@codecompareAndSet}.
*
*@paramexpecttheexpectedvalue
*@paramupdatethenewvalue
*@returntrueifsuccessful.
*/
publicfinalbooleanweakCompareAndSet(longexpect,longupdate){
returnunsafe.compareAndSwapLong(this,valueOffset,expect,update);
}
/**
*Atomicallyincrementsbyonethecurrentvalue.
*
*@returnthepreviousvalue
*/
publicfinallonggetAndIncrement(){
while(true){
longcurrent=get();
longnext=current+1;
if(compareAndSet(current,next))
returncurrent;
}
}
/**
*Atomicallydecrementsbyonethecurrentvalue.
*
*@returnthepreviousvalue
*/
publicfinallonggetAndDecrement(){
while(true){
longcurrent=get();
longnext=current-1;
if(compareAndSet(current,next))
returncurrent;
}
}
/**
*Atomicallyaddsthegivenvaluetothecurrentvalue.
*
*@paramdeltathevaluetoadd
*@returnthepreviousvalue
*/
publicfinallonggetAndAdd(longdelta){
while(true){
longcurrent=get();
longnext=current+delta;
if(compareAndSet(current,next))
returncurrent;
}
}
/**
*Atomicallyincrementsbyonethecurrentvalue.
*
*@returntheupdatedvalue
*/
publicfinallongincrementAndGet(){
for(;;){
longcurrent=get();
longnext=current+1;
if(compareAndSet(current,next))
returnnext;
}
}
/**
*Atomicallydecrementsbyonethecurrentvalue.
*
*@returntheupdatedvalue
*/
publicfinallongdecrementAndGet(){
for(;;){
longcurrent=get();
longnext=current-1;
if(compareAndSet(current,next))
returnnext;
}
}
/**
*Atomicallyaddsthegivenvaluetothecurrentvalue.
*
*@paramdeltathevaluetoadd
*@returntheupdatedvalue
*/
publicfinallongaddAndGet(longdelta){
for(;;){
longcurrent=get();
longnext=current+delta;
if(compareAndSet(current,next))
returnnext;
}
}
/**
*ReturnstheStringrepresentationofthecurrentvalue.
*@returntheStringrepresentationofthecurrentvalue.
*/
publicStringtoString(){
returnLong.toString(get());
}
publicintintValue(){
return(int)get();
}
publiclonglongValue(){
returnget();
}
publicfloatfloatValue(){
return(float)get();
}
publicdoubledoubleValue(){
return(double)get();
}
}
AtomicLong的代码很简单,下面仅以incrementAndGet()为例,对AtomicLong的原理进行说明。
incrementAndGet()源码如下:
publicfinallongincrementAndGet(){
for(;;){
//获取AtomicLong当前对应的long值
longcurrent=get();
//将current加1
longnext=current+1;
//通过CAS函数,更新current的值
if(compareAndSet(current,next))
returnnext;
}
}
说明:
(01)incrementAndGet()首先会根据get()获取AtomicLong对应的long值。该值是volatile类型的变量,get()的源码如下:
//value是AtomicLong对应的long值
privatevolatilelongvalue;
//返回AtomicLong对应的long值
publicfinallongget(){
returnvalue;
}
(02)incrementAndGet()接着将current加1,然后通过CAS函数,将新的值赋值给value。
compareAndSet()的源码如下:
publicfinalbooleancompareAndSet(longexpect,longupdate){
returnunsafe.compareAndSwapLong(this,valueOffset,expect,update);
}
compareAndSet()的作用是更新AtomicLong对应的long值。它会比较AtomicLong的原始值是否与expect相等,若相等的话,则设置AtomicLong的值为update。
AtomicLong示例
//LongTest.java的源码
importjava.util.concurrent.atomic.AtomicLong;
publicclassLongTest{
publicstaticvoidmain(String[]args){
//新建AtomicLong对象
AtomicLongmAtoLong=newAtomicLong();
mAtoLong.set(0x0123456789ABCDEFL);
System.out.printf("%20s:0x%016X\n","get()",mAtoLong.get());
System.out.printf("%20s:0x%016X\n","intValue()",mAtoLong.intValue());
System.out.printf("%20s:0x%016X\n","longValue()",mAtoLong.longValue());
System.out.printf("%20s:%s\n","doubleValue()",mAtoLong.doubleValue());
System.out.printf("%20s:%s\n","floatValue()",mAtoLong.floatValue());
System.out.printf("%20s:0x%016X\n","getAndDecrement()",mAtoLong.getAndDecrement());
System.out.printf("%20s:0x%016X\n","decrementAndGet()",mAtoLong.decrementAndGet());
System.out.printf("%20s:0x%016X\n","getAndIncrement()",mAtoLong.getAndIncrement());
System.out.printf("%20s:0x%016X\n","incrementAndGet()",mAtoLong.incrementAndGet());
System.out.printf("%20s:0x%016X\n","addAndGet(0x10)",mAtoLong.addAndGet(0x10));
System.out.printf("%20s:0x%016X\n","getAndAdd(0x10)",mAtoLong.getAndAdd(0x10));
System.out.printf("\n%20s:0x%016X\n","get()",mAtoLong.get());
System.out.printf("%20s:%s\n","compareAndSet()",mAtoLong.compareAndSet(0x12345679L,0xFEDCBA9876543210L));
System.out.printf("%20s:0x%016X\n","get()",mAtoLong.get());
}
}
运行结果:
get():0x0123456789ABCDEF intValue():0x0000000089ABCDEF longValue():0x0123456789ABCDEF doubleValue():8.1985529216486896E16 floatValue():8.1985531E16 getAndDecrement():0x0123456789ABCDEF decrementAndGet():0x0123456789ABCDED getAndIncrement():0x0123456789ABCDED incrementAndGet():0x0123456789ABCDEF addAndGet(0x10):0x0123456789ABCDFF getAndAdd(0x10):0x0123456789ABCDFF get():0x0123456789ABCE0F compareAndSet():false get():0x0123456789ABCE0F
以上所述是小编给大家介绍的Javaconcurrency之AtomicLong原子类,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对毛票票网站的支持!