JVM系列(四)— 原子性、可见性与有序性

上一篇讲了Java内存模型的相关知识,模型设计正是围绕着并发过程中如何处理原子性,可见性和有序性这3个特征来建立的

一、原子性(Atomicity)

  原子性的概念无需多说,熟悉事物的4个特性的应该比较熟悉这个概念

  由Java内存模型来直接保证的原子性变量操作包括read,load,assign,use,store,write。我们大致可以认为基本数

据类型的访问读写是具备原子性的(double和long有非原子性协定,不过读者只要知道就可以了,无须在意这两种几乎不会

发生的例外)

  如果应用场景需要提供更大范围的原子性保证,Java内存模型还提供了lock和unlock操作来满足这种需求,虚拟机未把

这两种操作直接开放给用户使用,但是提供了更高层次的字节码指令:monitorenter和monitorexit来隐式的使用这两个操作,

这两个字节码反映到Java代码中就是同步块——synchronized关键字,因此,在synchronized块之间的操作具备原子性

二、可见性(Visibility)

  可见性是指当一个线程修改了共享变量的值,其他线程能够立即得知这个修改。

  上一篇详细讲了volatile变量的一些特性,与普通变量的区别是,volatile的特殊规则保证了新值能立即同步到主内存,以

及每次使用前立即从主内存刷新。因此volatile变量保证了多线程操作时变量的可见性。

  除了volatile,Java还有两个关键字也实现了可见性:synchronized和final。

  synchronized同步块的可见性,是由"对一个变量执行unlock操作之前,必须先把此变量同步回主内存中(执行store和

write)"这条规则获得的,而final关键字的可见性是指:被final修饰的字段在构造器中一旦初始化完成,其他字段就能看见

final字段的值,也就是final域能确保初始化过程的安全性。

三、有序性(Ordering)

  一句话:如果在本线程内观察,所有的操作都是有序的;如果在一个线程中观察另一个线程,所有的操作都是无序的。

前半句是指"线程内表现为串行的语义";后半句是指"指令重排序"现象和"工作内存与主内存同步延迟"现象。

  Java提供了两个关键字来保证有序性:volatile和synchronized,volatile本身包含禁止指令重排序的语义,synchronized

则是由"一个变量在同一个时刻只允许一条线程对其进行lock操作"的规则来获得。

结语:

  以上介绍了并发中3种重要的特性,有没有发现,synchronized关键字满足了全部3种特性,看起来是万能的,的确,大部分

并发控制操作都能用synchronized来实现,,但是这也造就了他对性能的影响,在下篇我会介绍下以虚拟机角度看,有关

锁优化的知识,也可能,关于并发的介绍全部挪到《Java并发编程实践》这一分类中

原文地址:https://www.cnblogs.com/yb38156/p/9433579.html