java内存模型JMM

java内存模型JMM

    jmm本身是一种抽象概念,实际并不存在,它描述的是一组规则或规范,通过这组规则或规范定义了程序中各个变量(包括实例字段、静态字段、构成数组对象的元素)的访问方式。

JMM中主内存

    1.存储java实例对象

    2.包括成员变量、类信息、常量、静态变量等

    3.属于数据共享的区域,多线程并发操作时,会引发线程安全问题

JMM中的工作内存

    1.存储当前方法的所有本地变量信息,本地变量对其他线程不可见

    2.字节码行号指示器,Native方法信息

    3.属于线程私有数据区域,不存在线程安全问题

JMM与java内存区域划分是不同的概念层次

    1.jmm描述的一组规则,围绕原子性、有序性,可见性展开

    2.相似点:都存在共享区域和私有区域

主内存与工作内存的数据存储类型与操作方式归纳

    1.方法里的基本数据类型本地变量将直接存储在工作内存的栈、帧结构中

    2.引用类型的本地变量:引用存储在工作内存中,实例存储在主内存中

    3.成员变量、static变量、类信息均会存储在主内存中

    4.主内存共享方式是线程各拷贝一份数据到工作内存,操作完成后刷新回主内存、

JMM如何解决可见性问题

1.指令重排序需要满足的条件

(1)单线程下不能改变程序的运行结果

(2)存在数据依赖关系的不许与重排序

概括来说:无法通过happens-before原则推导出来的,才能进行指令的重排序

A操作的结果需要对B操作可见,则A与B存在happens-before关系

happens-before的八大原则

1,程序次序规则:一个线程内,按照代码顺序,书写在前面的操作先行发生于书写在后面的操作;

2,锁定规则:一个unLock操作先行发生于后面对同一个锁的lock操作;

3. volatile变量规则:对一个变量的写操作先行发生于后面对这个变量的读操作;

4,传递规则:如果操作A先行发生于操作B,而操作B又先行发生于操作C,则可以得出操作A先行发生于操作C;

5,线程启动规则: Thread对象的start()方法先行发生于此线程的每一个动作;

6,线程中断规则:对线程interrupt()方法的调用先行发生于被中断线程的代码检测到中断时间的发生

7·线程终结规则:线程中所有的操作都先行发生于线程的终止检测,我们可以通过Thread.join()方法结束, Thread.isAlive()的返回值手段检测到线程已经终止执行;

8,对象终结规则:一个对象的初始化完成先行发生于他的finalize()方法的开始;

happens-before的概念

如果两个操作不满足上述任意一个happens-before规则,那么这两个操作就没有顺序的保障, JVM可以对这两个操作进行重排序;

如果操作A happens-before操作B,那么操作A在内存上所做的操作对操作B都是可见的。

volatile : JVM提供的轻量级同步机制

保证被volatile修饰的共享变量对所有线程总是可见的

禁止指令重排序优化

JMM如何解决可见性问题

1、volatile变量为何立即可见?

当写一个volatile变量时, JMM会把该线程对应的工作内存中的共享变量值刷新到主内存中

当读取一个volatile变量时, JMM会把该线程对应的工作内存置为无效。

2、volatile如何禁止重排优化

内存屏障( Memory Barrier )

1·保证特定操作的执行顺序

2,保证某些变量的内存可见性

通过插入内存屏障指令禁止在内存屏障前后的指令执行重排序优化

强制刷出各种CPU的缓存数据,因此任何CPU上的线程都能读取到这 ,些数据的最新版本

volatile和synchronized的区别

1. volatile本质是在告诉JVM当前变量在寄存器(工作内存)中的值是不确定的,需要从主存中读取; synchronized则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住直到该线程完成变量操作为止

2, volatile仅能使用在变量级别; synchronized则可以使用在变量、方法知类级别

3. volatile仅能实现变量的修改可见性,不能保证原子性;而 synchronized则可以保证变量修改的可见性和原子性

4, volatile不会造成线程的阻塞; synchronized可能会造成线程的阻塞

5, volatile标记的变量不会被编译器优化; synchronized标记的变量可以

你可能感兴趣的:(java,java面试题)