java
您现在所在的位置:首页>企业动态>java

成都Java培训:Java内存模型分析与通过volatile解决并发编程问题

编辑:学到牛牛IT培训    发布日期: 2022-04-28 10:28:47  

JMM(java">Java Memory Model)是java内存模型的缩写,和JVM(Java Virtual Machine)是完全不同的概念(虽然它们看起来有点像)。

前面讲解的是计算机的内存模型,这里我们开始讲解的是Java中的内存模型,因为Java是跨平台的,它如果要兼容各个系统,自然内部底层就要做好很多工作,包括内存模型也得自己设计。通过了解学习了Java的内存模型,我们就能了解程序中对变量的访问规则,或是程序的执行次序,也更好的帮助我们解决一些在并发情况下的程序问题。

Java内存模型规定所有的变量都是存在主存当中(类似内存),而每个线程都有自己的工作内存(类似高速缓存)。

而关于并发编程的三要素,Java又是怎样处理的呢?

1.原子性

Java中,对基本数据变量的读取和赋值是原子性操作,除此以外,基本就需要自己使用各种分布式锁、事务等逻辑上的代码来保证了。

具有原子性的操作很少,例如x=1,这个操作是原子性的,将常量1赋值给x。

但是x++和x=x+1就不是了,它一是读取了x的值,然后x进行加1操作,最后再把结果写入x的值中,整整算3个操作。这其中任何一步的间隔中,都可能有其他线程获取到该变量导致干扰了运算结果。

2.可见性

对于可见性,Java提供了volatile关键字来保证可见性,本文的主角终于出场了。

普通的共享变量,是不能保证可见性的,因为它在被线程修改后,什么时候被写入主存是不确定的,此时内存中可能还是旧变量,因此无法保证可见性。

但是当一个共享变量被volatile修饰后,它会保证修改的值会立即被更新到主存,当有其他线程需要读取时,它会去内存中读取新的值。

3.有序性

前面我们已经提过了:指令重排,这里同样,可以利用volatile关键字来保证一定的有序性。

添加了volatile修饰的共享变量,是被禁止指令重排的。

但是并不是禁止了所有的指令重排,而仅是针对于volatile修饰的变量,在它前面的操作和代码,有可能会相互排序,但是无论如何,它们都不会排到volatile变量的后面。volatile后面的操作也是,不会排到它前面。

并且不仅仅是固定了前后操作的位置,它还能保证当执行到它时,它前面的操作是必定执行完毕了的,且这个执行结果对它和它后面的语句都是可见的。

4.总结

由此可见,volatile常被用于解决并发编程下的可见性和有序性问题,但是它并没有解决原子性的能力。

另外,通过synchronized和Lock也算是能保证原子性、可见性、有序性,因为它们直接“封锁了现场”,保证同一时刻只有一个线程能获取锁然后执行同步代码,既然相当于变成了单线程操作,自然也不存在并发情况下的三个问题了。不过,这种方式显然是会影响效率的。

免费试学
课程好不好,不如实地听一听

封闭学习

2

1

联系我们

电话:028-61775817

邮箱:1572396657@qq.com

地址:成都高新西区西芯大道4号

  • 学到牛牛在线咨询

    扫一扫,免费咨询

  • 学到牛牛公众号

    微信公众号

学一流技术,找高薪工作

7-24小时服务热线:

028-61775817

版权声明 网站地图

蜀ICP备2021001672号

课程问题轻松问