前言
Java内存模型都是围绕着原子性、有序性和可见性展开的。为了在适当的场合,确保线程间的有序性、可见性和原子性。Java使用了一些特殊的操作或者关键字来声明、告诉虚拟机,在这个地方,要尤其注意,不能随意变动优化目标指令。关键字volatile就是其中之一。
Java内存模型
1.原子性(Atomicity )
原子性是指一个操作是不可中断的。即使是在多个线程一起执行的时候,一个操作一旦开始,就不会被其他线程干扰。
2.可见性(Visibility)
可见性是指一个线程修改了某一个共享变量的值时,其他线程是否能够立即知道这个修改。显然,对于串行程序来说,可见性问题是不存在的。因为你在任何一个找找步骤中修改某个变量,在后续的步骤中读取这个变量的值时,读取的一定是修改后的新值。
3.有序性(Ordering)
对于一个线程的执行代码而言,我们总是习惯性地认为代码是从前往后依次执行的。这么理解也不能说完全错误,因为就一个线程而言,确实会表现成这样。但是,在并发时,程序的执行可能就会出现乱序。给人的直观感受是:写在前面的代码,会在后面执行。听起来有些不可思议,是吗?有序性问题的原因是程序在执行时,可能会进行指令重排,重排后的指令与原指令的顺序未必一致。
volatile
如果你查阅英文字段有关volatile的解释,你会得到最常用的解释是“易变的、不稳定的”。这也正是使用volatile的语义。
当你用关键字volatile声明一个变量时,就等于告诉了虚拟机,这个变量极有可能会被某些程序或者线程修改。为了确保这个变量被修改后,应用程序范围内的所有线程都能够”看到”这个改动,虚拟机就必须采用一些特殊的手段,保证这个变量的可见性等特点。
z比如,根据编译器的优化规则,如果不使用关键字volatile声明变量,那么这个变量被修改后,其他线程可能并不会被通知到,甚至在别的线程中,看到变量的修改顺序都会是反的。一旦使用关键字volatile,虚拟机就会特别小心地处理这种情况。
关键字volatile并不能代替锁,它也无法保证一些复合操作的原子性。比如下面的例子,通过关键字volatile是无法保证i++的原子性操作的
执行上述代码,如果第7行i++是原子性的,那么最终的值应该是100000。但实际上,上述代码的蔬菜总是会小于100000。
此外,关键字volatile也能保证数据的可见性和有序性。
领取 专属20元代金券
Get大咖技术交流圈