服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - Java教程 - 学习Java内存模型JMM心得

学习Java内存模型JMM心得

2021-03-09 14:17钟绍威 Java教程

这篇文章主要介绍了学习Java内存模型JMM的心得以及对其原理做了深入的介绍,有兴趣的朋友学习下吧。

有时候编译器、处理器的优化会导致runtime与我们设想的不一样,为此java对编译器和处理器做了一些限制,java内存模型(jmm)将这些抽象出来,这样编写代码时就无需考虑那么多底层细节,并保证“只要遵循jmm的规则编写程序,其运行结果一定是正确的”。

jmm的抽象结构

在java中,所有的实例、静态变量存储在堆内存中,堆内存是可以在线程间共享的,这部分也称为共享变量。而局部变量、方法定义参数、异常处理参数是在栈中的,栈内存不在线程间共享。

而由于编译器、处理器的优化,会导致共享变量出现可见性问题,像在多核处理器中(multi-processor),线程可以在不同的处理器上执行,而处理器之间缓存不一致,会使共享变量出现可见性问题,有可能两个线程看到同一个变量不同值。

jmm将这些硬件做的优化抽象成每个线程都有一个本地内存。需要读写共享变量时,从主内存中拷贝一份到本地内存。当写共享变量时,先写到本地内存中去,在将来某个时间再刷新到主内存中。当再次读共享变量时,则只会从本地内存中读取。

这样线程间通讯就需要经过两步:

写线程:刷新本地内存到主内存中去读线程:从主内存读取更新后的值

这样在写-读之间就有一个延迟:本地内存什么时候刷新到主内存中去?导致可见性问题,不同线程可能看到的共享变量不一样。

学习Java内存模型JMM心得

happens-before

从字面上看happens-before的意思是“发生在此之前”。这是java对程序执行顺序制定的规则,实现同步必须遵循该规则。这样程序员只需要写出正确的同步程序,happens-before保证运行结果不会错。

a happens-before b,不仅仅表示a在b之前执行,还意味着a的执行结果对b可见,这保证了可见性。

a happens-before b,a也不一定要在b之前执行,如果ab交替,执行结果任然正确,则允许编译器、处理器进行优化重排序。所以只要程序结果正确,编译器、处理器怎么优化,怎么重排序都没问题,都是好的。

happens-before规则

程序顺序规则:在一个线程中,前面的操作happens-before后面的操作锁规则:对同一个锁,解锁happens-before加锁 volatile域规则:写volatile变量,happens-before后面任意一个读这个volatile变量的操作传递性:a happens-before b,b happens-before c,则a happens-before c start()规则:如果线程a执行threadb.start() 那么threadb.start() happens-before 线程b中任何操作 join()规则:如果线程a执行threadb.join(),那么线程b中的所有操作happens-before threadb.join()

下面这个示例有助于理解happens-before

?
1
2
3
double pi = 3.14; //a
double r = 1.0; //b
double area = pi * r *r; //c

这里有三个happens-before关系,规则1、2是程序顺序规则,规则3是传递性规则推导出来的:

a happens-before b b happens-before c a happens-before c

c依赖于a、b,但是a和b谁也不依赖。所以即使a和b重排序,执行结果也不会发生变化,这种重排序,jmm是运行的。

下面两种执行顺序的结果都是正确的。

学习Java内存模型JMM心得

以上就是我们给大家整理的关于java内存模型jmm学习心得的全部内容,更多问题大家可以在下方留言讨论,感谢你对服务器之家的支持。

原文链接:http://www.cnblogs.com/wewill/p/8081394.html

延伸 · 阅读

精彩推荐