课程咨询: 400-996-5531 / 投诉建议: 400-111-8989
认真做教育 专心促就业
随着互联网的不断发展,越来越多的人都在学习软件编程开发等互联网相关的技术,而今天我们就通过案例分析来了解一下,java内存模型执行特性都有哪些。
Java 内存模型是围绕着在并发过程中如何处理这 3 个特性来建立的,这里先给出定义和基本实现的简单介绍,后面会逐步展开分析。
原子性(Atomicity)
原子性,即一个操作或者多个操作要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行。
即使在多个线程一起执行的时候,一个操作一旦开始,就不会被其他线程所干扰。
可见性(Visibility)
可见性是指当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值。
正如上面“交互操作流程”中所说明的一样,JMM 是通过在线程 1 变量工作内存修改后将新值同步回主内存,线程 2 在变量读取前从主内存刷新变量值,这种依赖主内存作为传递媒介的方式来实现可见性。
有序性(Ordering)
有序性规则表现在以下两种场景:
线程内,从某个线程的角度看方法的执行,指令会按照一种叫“串行”(as-if-serial)的方式执行,此种方式已经应用于顺序编程语言。
线程间,这个线程“观察”到其他线程并发地执行非同步的代码时,由于指令重排序优化,任何代码都有可能交叉执行。
起作用的约束是:对于同步方法,同步块(synchronized 关键字修饰)以及 volatile 字段的操作仍维持相对有序。
Java 内存模型的一系列运行规则看起来有点繁琐,但总结起来,是围绕原子性、可见性、有序性特征建立。
归根究底,是为实现共享变量的在多个线程的工作内存的数据一致性,多线程并发,指令重排序优化的环境中程序能如预期运行。
happens-before 关系
介绍系列规则之前,先了解一下 happens-before 关系:用于描述下 2 个操作的内存可见性。如果操作 A happens-before 操作 B,那么 A 的结果对 B 可见。
happens-before 关系的分析需要分为单线程和多线程的情况:
单线程下的 happens-before,字节码的先后顺序天然包含 happens-before 关系:因为单线程内共享一份工作内存,不存在数据一致性的问题。
在程序控制流路径中靠前的字节码 happens-before 靠后的字节码,即靠前的字节码执行完之后操作结果对靠后的字节码可见。
然而,这并不意味着前者一定在后者之前执行。实际上,如果后者不依赖前者的运行结果,那么它们可能会被重排序。
多线程下的 happens-before,多线程由于每个线程有共享变量的副本,如果没有对共享变量做同步处理,线程 1 更新执行操作 A 共享变量的值之后,线程 2 开始执行操作 B,此时操作 A 产生的结果对操作 B 不一定可见。
为了方便程序开发,Java 内存模型实现了下述支持 happens-before 关系的操作:
程序次序规则,一个线程内,按照代码顺序,书写在前面的操作 happens-before 书写在后面的操作。
锁定规则,一个 unLock 操作 happens-before 后面对同一个锁的 lock 操作。
volatile 变量规则,对一个变量的写操作 happens-before 后面对这个变量的读操作。
传递规则,如果操作 A happens-before 操作 B,而操作 B 又 happens-before 操作 C,则可以得出操作 A happens-before 操作 C。
线程启动规则,Thread 对象的 start() 方法 happens-before 此线程的每个一个动作。
线程中断规则,对线程 interrupt() 方法的调用 happens-before 被中断线程的代码检测到中断事件的发生。
线程终结规则,线程中所有的操作都 happens-before 线程的终止检测,我们可以通过 Thread.join() 方法结束、Thread.isAlive() 的返回值手段检测到线程已经终止执行。
对象终结规则,一个对象的初始化完成 happens-before 它的 finalize() 方法的开始。
【免责声明】:本内容转载于网络,转载目的在于传递信息。文章内容为作者个人意见,本平台对文中陈述、观点保持中立,不对所包含内容的准确性、可靠性与完整性提供形式地保证。请读者仅作参考。更多内容请在707945861群中学习了解。