java高并发程序设计(三)java内存模型JMM和volatile关键字

JMM的引出

我们需要在了解并行机制的基础上定义一种规则,保证多个线程间可以有效正确的一起工作

JMM的关键三个技术点

原子性(atomicity)
这里写图片描述
原子就是不可再分的
对于一个不可再分的操作来讲,要么完成,要么完不成,不会说我做了一半被另一个人干扰了,很多cpu指令都是原子性的操作
但是像我们写的一些程序代码不一定是原子性的,举例:i++
I++
先把i读出来,然后对i进行++操作,然后将加完的数据再写回i中
当多个线程对i进行i++操作的时候

I肯定是一个全局静态变量,这样他们之间就可能有冲突

比如有一个线程把i读出来了,读到了1,另一个线程在这个线程做加法的时候也把i读到了1,那么这两个线程同时对i进行加1操作,然后把各自的值写回i中,那么i就是2,而原本两个线程同时对i+操作,i应该是3
这里写图片描述
有序性:计算机真实执行代码的时候不一定是按照你程序的语序来执行的,比如write这个函数,对flag赋值为true,对a赋值为1

Reader函数判断出flag是否为true,为true了就对a进行+1操作
大家都会觉得flag=true了,a一定等于1,然后进入方法体内对a+1变成2

但是实际上这个是不一定的
如果writer和reader在两个线程上
线程a可能先去执行flag=true,然后执行a=1
而线程b可能先看到flag=true而没有看到a=1,而这个时候a有可能还未0,而线程b人为a这时候一定等于1
而a=1有可能在写线程中还未执行
这里写图片描述
这里的指令是计算机的汇编指令
取出指令IF:一条指令开始执行了,我就把它取出来
然后取出寄存器操作数:即参数ID
然后呢我才去执行和有效地址计算
执行完后我要做存储器的访问
最终我要将数据写回到寄存器中

每一部分可能用到不同的硬件
指令重排问题

可见性:指的是当一个线程修改了某一个共享变量的值,其他线程是否能够立即知道这个修改结果

volatile关键字
为了在适当的场合,确保线程的有序性,可见性和原子性,java使用了一些特殊的操作或者关键字来申明,告诉JVM,在这个地方,不能随意变动优化目标指令的执行顺序,关键字volatile就是其中之一

volatile对于保证操作的原子性是有非常大的帮助的,但是它并不能代替所,它也不能保证一些复合操作的原子性

猜你喜欢

转载自blog.csdn.net/bsfz_2018/article/details/80085827