JVM学习(JMM内存模型知识)

JMM内存模型学习

学习JMM内存模型,我们先从基础的入手,然后再从一步步的深入讲解来让大家对这些知识理解透彻。我尽量把我认识和知道的只是来分享给大家。
以下部分语句转载自文章https://www.jianshu.com/p/8a58d8335270

1、线程之间的通信

线程的通信是指线程之间以何种机制来交换信息。在编程中,线程之间的通信机制有两种,共享内存和消息传递。
在共享内存的并发模型里,线程之间共享程序的公共状态,线程之间通过写-读内存中的公共状态来隐式进行通信,典型的共享内存通信方式就是通过共享对象进行通信。
在消息传递的并发模型里,线程之间没有公共状态,线程之间必须通过明确的发送消息来显式进行通信,在java中典型的消息传递方式就是wait()和notify()。

2、现代计算机内存模型

大家都知道我们现在的计算机里面的硬件内容,其中就包括了CPU和内存,然而在现代计算机中,CPU的运算速度已经远远大于内存的存取速度,所以现代的计算机不得不引进一层与高速CPU运算速度大致差不多的高速缓冲区。将运算需要的数据拿到缓冲区里,这样就能提高CPU的运算速度,不需要等待内存了。
下图也就是可以描述当代计算机的内存模型的一个图了。
那么这种内存模型会给我们带来什么问题呢?众所周知,大家在开发时肯定难免遇到高并发、多线程这样的开发状况。那么比如有两个不同的线程,那么他们两个线程之间看到的缓存的内容肯定也是不一样的,这个特性会对内存操作的执行顺序产生重要的影响:处理器对内存的读/写操作的执行顺序,不一定与内存实际发生的读/写操作顺序一致!
JVM学习(JMM内存模型知识)_第1张图片
可能由于代码的并行运算的执行性质,达成的效果可能跟我们预期想象的完全不一样,所以这也是现在内存区域的一种缺陷。

3、JMM,Java内存模型

下面是一个大概的JMMJava内存模型,它是分配给每个线程单独一个工作内存,当然根据上面介绍的缓冲区的应用,想必大家对工作内存的作用也应该知晓大概。在这先给大家介绍一下JMM的八大操作:
以下是JMM内存间的交互操作:
Java内存模型中定义了8种操作来完成,虚拟机保证了每种操作都是原子的。
①Lock:加锁,作用于主内存的变量,作用是把一个共享变量标识为一个线程独占状态。
②UnLock:解锁,作用于主内存变量,作用是把一个处于锁定状态的变量释放,然后可以被其他线程锁定。
③read:读取,作用于主内存中的变量,作用是从主内存中读取出后面load操作要用到的变量。
④load:载入,作用于主内存中的变量,把刚才read的值放入工作内存的副本中。
⑤use:使用,作用于工作内存中的变量,当线程执行某个字节码指令需要用到相应的变量时,把工作内存中的变量副本传给执行引擎。
⑥assign:赋值,作用于工作内存中的变量,把一个从执行引擎接收的值,复制给工作内存中的变量。
⑦store:存储,作用于工作内存中的变量,把工作内存中的变量送到主内存,给后续的write使用。
⑧write:写入,作用于主内存的变量,把store的工作内存中的变量值,写入主内存中。

JVM学习(JMM内存模型知识)_第2张图片
这个时候的Java代码运行,其实也难免会发生高并发状况下的脏读等错误,比如主内存中的值为1,这个时候两个不同的线程都拿到这个值拿到了工作内存,那么这时候都对这个值进行+1,但实际上我们知道我们想要的效果是1+1+1等于3,但这时候不同的线程都看不到对方的值,这时候都将2的值返回了回来,我们于是看到主内存中的值只是更新到了2。这就是我们说的发生的错误。那么这个时候我们应该怎么解决这些问题呢?
Synchronized:保证运行期间的同步。在某个线程执行的时候,另外一个线程是不能对这个方法进行执行的,就是在高并发状态下,一个方法不会同时被两个线程所调用,只能保持只有一个线程在调用它,这样也就能保证它的不出错。
Volatile:用Volatile关键字来保证数据的可见性,用MESI数据一致性协议来保证数据的一致。让数据在store操作的时候lock住 让read write 等操作锁住,直到主内存更新 这时候在MESI的一致协议也就是总线会监听到有人经过,这时候等待更新完成并且unlock后重新读取数据 这就是数据的可见性

总结

以上就是这次想给大家简单的科普一下JMM内存模型的内容,以及Volatile在JMM中操作的实现。希望能够加深大家的印象,促进大家的学习。有什么不对的欢迎指出,谢谢

你可能感兴趣的:(JVM虚拟机,java,内存结构,多线程)