在JUC(并发包)里经常会使用到Unsafe
这个类,那么了解这个类,就成为了下面学习的重中之重
1 | /** |
putOrderedObject整理
这方法纠结了我很久,因为doc上很简略,大体就是讲对非volatile变量的修改对其他线程不会立即生效
- 那么这货有什么用?
- 这货和普通写入有什么区别吗?(因为普通写入对其他线程也不会立即生效)
下面的Bug Report是为什么添加“lazySet”的初衷:
“As probably the last little JSR166 follow-up for Mustang,
we added a “lazySet” method to the Atomic classes
(AtomicInteger, AtomicReference, etc). This is a niche
method that is sometimes useful when fine-tuning code using
non-blocking data structures. The semantics are
that the write is guaranteed not to be re-ordered with any
previous write, but may be reordered with subsequent operations
(or equivalently, might not be visible to other threads) until
some other volatile write or synchronizing action occurs).
我们添加了“lazySet”一方法给AtomicX这些类(比如AtomicInteger、AtomicReference等)。这个方法在使用非阻塞数据结构调整代码的情况下很有用。它的作用主要表现在 保证写入前的操作的不会被重排序,写入后的操作可能会被重排序(换言之就是写入后对其他线程不会立即可见) 直到有其他的volatile写入或者同步操作发生。
The main use case is for nulling out fields of nodes in
non-blocking data structures solely for the sake of avoiding
long-term garbage retention; it applies when it is harmless
if other threads see non-null values for a while, but you’d
like to ensure that structures are eventually GCable. In such
cases, you can get better performance by avoiding
the costs of the null volatile-write. There are a few
other use cases along these lines for non-reference-based
atomics as well, so the method is supported across all of the
AtomicX classes.
这个方法的主要用途是 在非阻塞数据结构中单独空出结点,来降低长时间的垃圾滞留问题来的性能问题;这能运用在就算其他线程看到非空值也没关系的情况下。但是你要确保这个结构确实能够被GC。在这种情况下,你能通过避免null值的写入,来获得更好的性能。
For people who like to think of these operations in terms of
machine-level barriers on common multiprocessors, lazySet
provides a preceeding store-store barrier (which is either
a no-op or very cheap on current platforms), but no
store-load barrier (which is usually the expensive part
of a volatile-write).”
对于那些在通用多处理器下需要考虑底层机器屏障的人来说,“lazySet”提供了预Store-Store屏障(对于现在的平台来说,要么无操作,要么代价不大),但是没有Store-Load屏障(通常需要付出较高的代价)
PS:因为“lazySet”其实就是“volatile”的削弱版,所以叫“weak volatile”也挺符合的。
“weak volatile”的场景:
“weak volatile”适用于对实时性要求不高的场景,该方法可以较大的节省性能消耗
一个链表中的某个节点被修改了,在volatile的情况下,整个链表都会一定被强制更新;而在”weak volatile”的情况下,不被强制更新,节省部分性能。- 在修改帖子状态的时,如果对性能要求很高,可以使用“lazySet”保证写入内存,但是对实时性的要求不高
具体的其他场景可以看下面的链接(表示第一个回答没看懂,功力深了后再来)
“weak volatile”的原理
volatile的工作原理是插入屏障,在写入的时候插入StoreStore,写完后插入StoreLoad,根据Doug Lea的说法,StoreLoad相比StoreStore更消耗资源
而“weak volatile”则是省去了最后的StoreLoad的步骤,相比插入两个屏障,“weak volatile”性能提升了不少
更加具体的底层原理可以看下面的链接