最近一直在学习java内存模型相关的知识内容,学习后的总结才能更上一层楼。那么java内存模型是干什么的?为什么需要他呢。
1,我们为什么需要JMM
我们在使用java开发的业务场景中,很多时候都会碰到并发的问题,在并发场景下,数据的安全就非常重要,那么我们为了保证数据安全需要满足三方面的特性:
- 原子性
原子性是指一个操作在执行的过程中,要么完成,要么就不完成,不能说在执行过程中还中断一下后继续运行。在java中,为了保证原子性,对应的关键字就是synchronized;- 可见性
可见性是指当多个线程访问同一个变量时,一个线程修改了变量的值后,其他的线程能够看到立即修改后的值。java当中,我们可以使用最多的volatile就是用来保证多线程操作时变量的可见性,除了volatile,Java中的synchronized和final两个关键字也可以实现可见性。;- 有序性
就是程序执行的顺序是按照我们代码的先后顺序进行的。在执行程序时,为了提高性能,编译器和处理器会对指令做重排序,在Java中,可以使用synchronized和volatile来保证多线程之间操作的有序性。volatile关键字会禁止指令重排。synchronized关键字保证同一时刻只允许一条线程操作。
JMM是一种规范,目的是解决由于多线程通过共享内存进行通信时,存在的本地内存数据不一致、编译器会对代码指令重排序、处理器会对代码乱序执行等带来的问题。
java内存模型(JMM)是什么:
Java内存模型(Java Memory Model ,JMM),在java中线程之间的共享变量存储在主内存中(main memory),每个线程都有一个私有的本地内存(local memory),本地内存中存储了该线程以读/写共享变量的副本。线程与线程之间不能直接访问对方本地内存中的变量副本,只能通过主内存来进行数据通信。

JMM内存模型原子操作有如下步骤,理解这些步骤可以让我们更深刻的理解java的内存模型。
- read(读取),从主内存中读取数据
- load(载入),将主内存读取到的数据载入到工作内存中
- use (使用),从工作内存中读取数据来计算
- assign(赋值),将计算好的值重新赋值到工作内存中
- store(存储),将工作内存数据写入主内存
- write(写入),将store过去的变量值赋值给主内存中的变量
- lock(锁定),将主内存变量加锁,标识为线程独占状态
- unlock(解锁),将主内存变量解锁,解锁后其他线程可以锁定该变量
JSR133给Java内存模型定义以下一组happen-before规则,了解下面的规则可以方便我们理解操作内存时的可见性问题
- 单线程规则:同一个线程中的每个操作都happens-before于出现在其后的任何一个操作。
- 对一个监视器的解锁操作happens-before于每一个后续对同一个监视器的加锁操作。
- 对volatile字段的写入操作happens-before于每一个后续的对同一个volatile字段的读操作。
- Thread.start()的调用操作会happens-before于启动线程里面的操作。
- 一个线程中的所有操作都happens-before于其他线程成功返回在该线程上的join()调用后的所有操作。
- 一个对象构造函数的结束操作happens-before与该对象的finalizer的开始操作。
- 传递性规则:如果A操作happens-before于B操作,而B操作happens-before与C操作,那么A动作happens-before于C操作。
通过本篇介绍,我们大致了解了JMM的具体作用,那么java当中具体给给我们提供了哪些方式来保证线程之间通信时数据的安全性,volatile和synchronized的使用就不得不提了,下一篇我们详细介绍这两个关键字的用法和区别。
网友评论