J.U.C原子工具类AtomicXXX中,set和lazySet的区别
来源:互联网 发布:手机视频制作软件 编辑:程序博客网 时间:2024/06/12 19:39
提到java原子类,不得不说下关键字volatile和内存可见性。内存可见性问题,可以看下《java并发编程实践》讲的很详细。下面的示例代码是错误的,因为没有使用volatile来保证内存的可见性,所以如果1个线程修改了共享变量,那么另外一个线程可能永远也看不到修改后的值。如果将stop修改成volatile类型的,就可以保证一个线程对volatile变量的修改,对另一个线程是可见的。
public class Test {private static boolean stop = false;// 以-server模式启动JVMpublic static void main(String[] args) throws Exception {new Thread(new Runnable() {public void run() {while (!stop) {}System.out.println("over");}}).start();Thread.sleep(200);stop = true;}}
volatile和可见性,可以看下“深入理解Java内存模型(四)——volatile”这篇文章讲解的很浅显易懂。
了解了volatile和可见性之后,我们回到主题看下set和lazySet的差别,jdk源码的javadoc描述的相当简单:
/** * Sets to the given value. * * @param newValue the new value */public final void set(int newValue) { value = newValue;}/** * Eventually sets to the given value. * * @param newValue the new value * @since 1.6 */public final void lazySet(int newValue) { unsafe.putOrderedInt(this, valueOffset, newValue);}
按照javadoc的字面意思:set()会立刻修改旧值,别的线程可以立刻看到更新后的值;而lazySet不会立刻(但是最终会)修改旧值,别的线程看到新值的时间会延迟一些。JDK bug database上有对lazySet的详细描述:
http://bugs.java.com/bugdatabase/view_bug.do?bug_id=7065550
http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6275329
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).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.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).
set()和volatile具有一样的效果(能够保证内存可见性,能够避免指令重排序),但是使用lazySet不能保证其他线程能立刻看到修改后的值(有可能发生指令重排序)。简单点理解:lazySet比set()具有性能优势,但是使用场景很有限。在网上没有找到lazySet和set的性能数据对比,而且CPU的速度很快的,应用的瓶颈往往不在CPU,而是在IO、网络、数据库等。对于并发程序要优先保证正确性,然后出现性能瓶颈的时候再去解决。因为定位并发导致的问题,往往要比定位性能问题困难很多。
在stackoverflow上,也有很人提问set和lazySet的问题:
http://stackoverflow.com/questions/1468007/atomicinteger-lazyset-vs-set
http://stackoverflow.com/questions/25840733/atomic-integer-lazyset-performance-gains
http://stackoverflow.com/questions/7557156/atomicxxx-lazyset-in-terms-of-happens-before-edges
本人不懂硬件和CPU,对于并发编程中很多问题,只能简单的知道,不能真正的理解。先记下来这些遇到的知识点,留作以后慢慢领悟!
- J.U.C原子工具类AtomicXXX中,set和lazySet的区别
- 理解AtomicXXX.lazySet方法
- J.U.C--原子变量类AtomicInteger的源码解析与原理分析
- J.U.C--同步工具类
- J.U.C之并发工具类:CyclicBarrier
- Java中j=j++与c语言中j=j++的区别
- 聊聊高并发(十八)理解AtomicXXX.lazySet方法
- J.U.C-包下的类分类
- 并发中CAS的含义及Java中AtomicXXX类的分析
- 【死磕Java并发】-----J.U.C之并发工具类:CyclicBarrier
- 【死磕Java并发】-----J.U.C之并发工具类:CountDownLatch
- 【死磕Java并发】-----J.U.C之并发工具类:Semaphore
- 【死磕Java并发】-----J.U.C之并发工具类:Exchanger
- J.U.C--同步容器类Collections
- J.U.C体系
- J.U.C
- “J.U.C”:ReentrantReadWriteLock
- “J.U.C”:Condition
- POJ 1654 Area 有向面积
- Candy
- python subprocess
- Android四大组件详解
- linux 下查看一个进程运行路径的方法
- J.U.C原子工具类AtomicXXX中,set和lazySet的区别
- 人见人爱A^B
- ARM PL330 DMA控制器开发(二)
- Redis关键点(rehash)<转>
- Qt 中界面间的执行调用QDialog::Accepted
- mac开发给字符串加入下划线的方法。
- Java Webservice调用总结
- BZOJ 1483 HNOI 2009 梦幻布丁 链表+启发式合并
- nodejs用流来对文件操作