是什么之间的区别lazySet
和set
方法AtomicInteger
? 该文件并没有太多的话要说lazySet
:
最终设置为给定值。
看来,储值不会立即设置为所需的值,但将改为按计划将在设定未来的某个时间。 但是,什么是该方法的实际应用? 任何例子吗?
是什么之间的区别lazySet
和set
方法AtomicInteger
? 该文件并没有太多的话要说lazySet
:
最终设置为给定值。
看来,储值不会立即设置为所需的值,但将改为按计划将在设定未来的某个时间。 但是,什么是该方法的实际应用? 任何例子吗?
直接从引“JDK-6275329:添加lazySet方法原子类” :
作为可能是最后一点JSR166随访野马,我们增加了一个“lazySet”方法对原子类(的AtomicInteger,的AtomicReference等等)。 这是一个特殊的方法使用非阻塞数据结构微调代码时有时是有用的。 语义是写保证不与任何先前的写重新排序,但可能与后续操作来重新排序(或等价地,可能不是其他线程可见),直到一些其他挥发性写或同步动作发生)。
主要的使用情况是用于归零出在非阻塞的数据结构仅仅是为了避免长期保留垃圾的缘故节点的字段; 它适用于当它是无害的,如果其他线程看到非空值了一段时间,但你想,以确保结构是最终GCable。 在这种情况下,你可以通过避免空挥发性写的成本获得更好的性能。 还有一些其他的用例沿着这些线路对非基准基于原子公司为好,这样的方法在所有AtomicX类的支持。
对于谁喜欢上常见的多处理器机器级的障碍来考虑这些操作的人,lazySet提供前述店店屏障(这是可以无操作或在当前平台很便宜),但没有店面负荷屏障(其通常是易失性读写的昂贵的部分)。
lazySet可用于RMW间线程通信,因为XCHG是原子的,作为用于可视性,当写线程处理修改的高速缓存行的位置,读取器线程的处理器将看到它在下一读,因为Intel的CPU的高速缓存一致性协议将garantee LazySet工作,但高速缓存线将在下一读取更新,再次,CPU有足够的现代化。
http://sc.tamu.edu/systems/eos/nehalem.pdf对于Nehalem的是一种多处理器平台,处理器必须“窥探”(窃听)地址总线用于其它处理器的能力访问系统存储器和其内部缓存。 他们用这种监听,以保持其内部高速缓存都与系统内存,并与其他互联处理器高速缓存一致性的能力。 如果通过窥探一个处理器检测到另一个处理器打算写入的存储器位置,它目前已经在共享状态高速缓存时,监听处理器会作废其高速缓存块迫使它来执行高速缓存线填充在下一次访问相同的存储器位置。
用于x86 CPU建筑 - oracle的热点JDK>
lazySet == unsafe.putOrderedLong == XCHG RW(ASM指令作为软屏障上nehelem Intel的CPU成本计算20个循环)
在x86(x86_64的)这样的屏障要便宜得多的性能代价比易失性或AtomicLong的getAndAdd,
在一个一个制片人,一个消费者队列的情况下,XCHG软屏障可以强制码的行lazySet(序列+ 1)之前为生产者线程发生之前的任何消费者线程的代码,将消耗(工作)的新的数据,当然消费者线程将需要以原子检查生产者序列通过正好一个使用compareAndSet(序列,序列+ 1)递增。
我之后热点的源代码追溯到找到lazySet到CPP代码精确映射: http://hg.openjdk.java.net/jdk7/jdk7/hotspot/file/9b0ca45cd756/src/share/vm/prims/unsafe。 CPP Unsafe_setOrderedLong - > SET_FIELD_VOLATILE定义- > OrderAccess:release_store_fence。 对于x86_64的,OrderAccess:release_store_fence被定义为使用XCHG指令。
你可以看到它是如何精确地定义JDK7(Doug Lea的正在开发一些新的工具和JDK 8): http://hg.openjdk.java.net/jdk7/jdk7/hotspot/file/4fc084dac61e/src/os_cpu/ linux_x86 / VM / orderAccess_linux_x86.inline.hpp
你也可以使用HDIS拆卸lazySet代码的组件行动。
还有一个相关的问题: 我们是否使用XCHG时需要MFENCE
lazySet和底层putOrdered的起源和效用的更广泛的讨论可以在这里找到: http://psy-lob-saw.blogspot.co.uk/2012/12/atomiclazyset-is-performance-win-for.html
总结:lazySet是它作为一个商店店面,而不是一个存储负载栅栏意义上的薄弱性写。 这归结为编译成一个MOV指令不能由编译器重新排序,而不是用于挥发性组显著更昂贵的指令lazySet是JIT。
当读值,你总是最终会做挥发性读取(用原子*获得()在任何情况下)。
lazySet提供了一个单一的作家一贯性写机制,即它是一个作家用lazySet递增计数器完全合法的,多线程递增相同的计数器将必须解决使用CAS,这是写入正是下发生竞争原子*为incAndGet的封面。
从并行原子包摘要
lazySet具有写入(分配)volatile变量除了它允许使用本身不征收重排的约束与普通的非易失性写入后续的(而不是以前的)内存的动作重新排序的记忆效应。 在其他使用上下文,lazySet可能归零出来的时候,垃圾收集,是永远不会再次访问参考的缘故适用。
如果您想了解lazySet那么你欠自己其他的解释太
用于访问和原子能的更新记忆效应一般遵循规则挥发物,如Java™语言规范的第17.4陈述。
GET具有读取volatile变量的内存效果。
组具有写入(分配)挥发性变量的记忆效应。
lazySet具有写入(分配)volatile变量除了它允许使用本身不征收重排的约束与普通的非易失性写入后续的(而不是以前的)内存的动作重新排序的记忆效应。 在其他使用上下文,lazySet可能归零出来的时候,垃圾收集,是永远不会再次访问参考的缘故适用。
weakCompareAndSet自动读取和写入有条件的变量,但不会产生任何的之前发生的排序,所以不提供任何担保相对于以前或以后的读取和比weakCompareAndSet的目标以外的任何变量写道。 compareAndSet和如getAndIncrement所有其他的读取和更新操作同时具有读取和写入volatile变量的内存效果。
这是我的理解,纠正我,如果我错了:你可以想想lazySet()
作为“半成品”挥发性:它基本上是在被其他线程读取方面的非易失性变量,即由lazySet设置的值可能不可见对其他线程。 但是,当另一写操作发生时变得易失性(可以是从其他线程)。 lazySet的我能想象的唯一影响是compareAndSet
。 所以,如果你使用lazySet()
get()
从其他线程可能仍然使用旧的价值,但compareAndSet()
总会有新的价值,因为它是一个写操作。
回复:尝试哑下来 -
你可以认为这是一个方式来对待挥发性场,如果它是不挥发物为特定的存储设备(例如:REF = NULL;)操作。
这是不完全准确,但它应该是足够的,你可以做之间“OK,我真的不关心”和“嗯,让我想想,对于一个比特”的决定。