Java中unsafe操作实例总结
Unsafe是Java无锁操作的基石,在无锁并发类中都少不了它们的身影,比如ConcurrentHashMap,ConcurrentLinkedQueue,都是由Unsafe类来实现的。相对于与Java中的锁,它基本无开销,会原地等待。本文主要介绍下Unsafe中的主要操作。
1compareAndSwap
/** *比较obj的offset处内存位置中的值和期望的值,如果相同则更新。此更新是不可中断的。 * *@paramobj需要更新的对象 *@paramoffsetobj中整型field的偏移量 *@paramexpect希望field中存在的值 *@paramupdate如果期望值expect与field的当前值相同,设置filed的值为这个新值 *@return如果field的值被更改返回true */ publicnativebooleancompareAndSwapInt(Objectobj,longoffset,intexpect,intupdate);
这个就是著名的CAS操作了,分为三步来做
- 获取obj对象中为offset的偏移值,这里假设为realVal
- 比较realVal和expect
- 如果相同,将该值更新为update,否则不更新
CAS家族还包括有,compareAndSwapObject(),compareAndSwapLong(),compareAndSwapInt()等等
用AtomicInteger中一个经典的例子来说明:
publicfinalintgetAndAdd(intdelta){ returnunsafe.getAndAddInt(this,valueOffset,delta); } //unsafe.getAndAddInt publicfinalintgetAndAddInt(Objectvar1,longvar2,intvar4){ intvar5; do{ /**获取原始值*/ var5=this.getIntVolatile(var1,var2); /**确认原始值没有被其它线程修改时,再执行更新var5+var4操作*/ }while(!this.compareAndSwapInt(var1,var2,var5,var5+var4)); returnvar5; }
2putOrder
/*** *Setsthevalueoftheintegerfieldatthespecifiedoffsetinthe *suppliedobjecttothegivenvalue.Thisisanorderedorlazy *versionofputIntVolatile(Object,long,int)
,which *doesn'tguaranteetheimmediatevisibilityofthechangetoother *threads.Itisonlyreallyusefulwheretheintegerfieldis *volatile
,andisthusexpectedtochangeunexpectedly. * *@paramobjtheobjectcontainingthefieldtomodify. *@paramoffsettheoffsetoftheintegerfieldwithinobj
. *@paramvaluethenewvalueofthefield. *@see#putIntVolatile(Object,long,int) */ publicnativevoidputOrderedInt(Objectobj,longoffset,intvalue);
将obj对象的偏移量为offset的位置修改为value,因为Java中没有内存操作,而Unsafe的这个操作正好补充了内存操作的不足。也可以用于数组操作,比如ConcurrentHashMap中就大量用到了该操作
Segments0= newSegment (loadFactor,(int)(cap*loadFactor), (HashEntry [])newHashEntry[cap]); Segment []ss=(Segment [])newSegment[ssize]; //往数组下标为0的位置,写入s0:ss[0]=s0 UNSAFE.putOrderedObject(ss,SBASE,s0);//orderedwriteofsegments[0]
需要注意的是obj需要设置为Volatile,否则对于其它线程会不可见
3putXxxVolatile
/***
*Setsthevalueoftheintegerfieldatthespecifiedoffsetinthe
*suppliedobjecttothegivenvalue,withvolatilestoresemantics.
*
*@paramobjtheobjectcontainingthefieldtomodify.
*@paramoffsettheoffsetoftheintegerfieldwithinobj
.
*@paramvaluethenewvalueofthefield.
*/
publicnativevoidputIntVolatile(Objectobj,longoffset,intvalue);
感觉和putOrderInt一样,因为必须设置为Volatile,否则有什么用呢?
以上就是本次给大家分享的知识点的全部内容,感谢大家对毛票票的支持。