您好,登录后才能下订单哦!
这篇文章给大家分享的是有关Java并发编程之关键字volatile的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。
被 volatile 修饰的变量
1.保证了不同线程对该变量操作的内存可见性
2.禁止指令重排序
Java 内存模型(Java Memory Model) 是 Java 虚拟机定义的一种规范,即每个线程都有自己的工作空间,线程对变量的操作都在线程的工作内存中完成,再同步到主存中,这样可能会导致不同的线程对共享变量的操作,在各自线程工作空间内不一样的问题。
而用 volatile 修饰的变量,线程对该变量的修改,会立刻刷新到主存,其它线程读取该变量时,会重新去主存读取新值。
CPU 为了提供程序的运行效率,会对代码的执行顺序进行重排,因此代码中各个语句的先后执行顺序有可能会变化,但是它会保证程序最终执行结果与代码顺序执行结果一致。
指令重排序会考虑数据之间的依赖性,不会影响单个线程内程序的执行结果
c = 2 可能在 a = 1之前执行
int a = 1; int c = 2;
volatile 修饰的变量具有有序性,即被 volatile 修饰的变量,在其前面的操作与在其后面的操作的执行顺序不能打乱。
int a= 1; volatile b = 2; int c = 2;
a = 1 一定在 c = 2 前面执行,volatile 的作用好像在两者之间插入了一个内存屏障
对于 volatile 的有序性应用,一般常用 double-check 的单例模式来说明
public class Singleton { private Singleton(){} private static volatile Singleton singleton; public static Singleton getSingleton(){ if (singleton == null){ synchronized(Singleton.class){ if (singleton == null){ singleton = new Singleton(); } } } return singleton } }
singleton = new Singleton(); 分为 3 步
1.new Singleton() 开辟堆内存空间
2.初始化 singleton 对象
3.将 singleton 对象指向堆内存地址
第 3 步可能在第 2 步之前执行,那么其它线程可能得到为初始化完成的 singleton 对象,造成异常。
程序顺序规则: 一个线程中的每个操作,happens-before于该线程中的任意后续操作
监视器锁规则:对一个线程的解锁,happens-before 于随后对这个线程的加锁
volatile 变量规则: 对一个 volatile 域的写,happens-before 于后续对这个 volatile 域的读
传递性:如果 A happens-before B ,且 B happens-before C, 那么 A happens-before C
start()规则: 如果线程A执行操作ThreadB_start()(启动线程B) , 那么A线程的ThreadB_start()happens-before 于B中的任意操作
join()原则: 如果A执行ThreadB.join()并且成功返回,那么线程B中的任意操作happens-before于线程A从ThreadB.join()操作成功返回。
interrupt()原则: 对线程interrupt()方法的调用先行发生于被中断线程代码检测到中断事件的发生,可以通过Thread.interrupted()方法检测是否有中断发生
finalize()原则:一个对象的初始化完成先行发生于它的finalize()方法的开始
1.volatile 只能作用于变量,synchronized 可以作用于变量,方法,代码块
2.volatile 不保证原子性,synchronized 可以保证
3.访问 volatile 修饰的变量不会阻塞,synchronized 可能会
感谢各位的阅读!关于“Java并发编程之关键字volatile的示例分析”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。