=========================================================================================================================
Volatile:
一旦一个共享变量被volatile修饰后,那么就具备了两层语义:
1、保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了这个变量的值,这新值对其他线程来说是立即可见的。
2、禁止进行指令重排序。
volaitle保证共享变量修改的可见性:
线程1和线程2 volatile共享变量var,当线程1更改变量var后,会使得线程2关于变量var的缓存行失效,让线程2去主存中读取var的值。
volatile不保证变量操作的原子性:
如果线程1从主存中读取了变量var后,还没来得及更新var的值就被阻塞了,此时线程2得到了执行,去主存中读取了var的值,并更新了值。然后
当线程再会到线程1执行时,线程1更新值时,var的值已经不是最新的了。
volatile保证指令指令有序性:
volatile关键字禁止指令重排序有两层意思:
1)当程序执行到volatile变量的读操作或者写操作时,在其前面的操作的更改肯定全部已经进行,且结果已经对后面的操作可见;在其后面的操作肯定还没有进行;
2)在进行指令优化时,不能将在对volatile变量访问的语句放在其后面执行,也不能把volatile变量后面的语句放到其前面执行。
volatile的原理和实现机制
前面讲述了源于volatile关键字的一些使用,下面我们来探讨一下volatile到底如何保证可见性和禁止指令重排序的。
下面这段话摘自《深入理解Java虚拟机》:
“观察加入volatile关键字和没有加入volatile关键字时所生成的汇编代码发现,加入volatile关键字时,会多出一个lock前缀指令”
lock前缀指令实际上相当于一个内存屏障(也成内存栅栏),内存屏障会提供3个功能:
1)它确保指令重排序时不会把其后面的指令排到内存屏障之前的位置,也不会把前面的指令排到内存屏障的后面;即在执行到内存屏障这句指令时,在它前面的操作已经全部完成;
2)它会强制将对缓存的修改操作立即写入主存;
3)如果是写操作,它会导致其他CPU中对应的缓存行无效。
volatile声明的共享变量不一定是线程安全的(因为不保证操作原子性)。
* 变量的写操作不依赖变量当前值,那么此volatile变量是线程安全的。否则,是线程不安全的。
=========================================================================================================================
Transicent:
关闭某个域的序列化。即对象中的此域不参加对象的序列化。
=========================================================================================================================
Native:
=========================================================================================================================
Interface中的 default 方法:
Java 8中新加了default关键字特性,旨在兼容优化、升级Interface。
在Java 8之前,若在Interface中增加了方法,所有implements此Interface的类都需要配合、实现新增的方法。也就造成了Interface一旦发布,就
不能新增方法的困扰。
default方法允许在Interface中增加接口的实现。而且implements此Interface的类可以覆盖、重写此方法。
当类implements的两个Interface中都有同一个名字的方法,那么类必须Override此方法,可以在Override的方法里选择调用某一个Interface的方法。
=========================================================================================================================
final :
final用于声明属性、方法和类,分别表示属性不可变、方法不可被覆盖、类不可被继承。
final 声明的变量,表示变量的引用的对象地址不能被改变,而被应用对象内部的值可以被改变。
final 声明的参数,表示参数在方法内部不能被修改。
=========================================================================================================================
static:
static 成员变量:表示是类的变量,不是对象的变量。此种变量在类加载到内存时就在内存中分配了空间并存储,可以直接通过类名访问。
static 成员方法:与static成员变量类似,可以直接通过类名访问。
static 代码块 :在类中独立于成员变量和成员函数的代码块,JVM在加载类时会执行static代码块,如果有多个代码块,JVM将会按顺序执行。需要
注意的是:static代码块只会被执行一次。
static 内部类 :static内部类是指被声明为static的内部类,它可以不依赖于外部实例对象而被实例化。