本期说一下Java 内存模型(Java Memory Model,JMM)及共享变量可见性问题。 以下内容出自本人整理的面试秘籍。 点击此处,无套路免费获取面试秘籍 答: Java 内存模型(Java Memory Model,JMM)抽象了线程和主内存之间的关系就比如说线程之间的共享变量必须存储在主内存中,规定了从 Java 源代码到 CPU 可执行指令的这个转化过程要遵守哪些和并发相关的原则和规范. 答: 在多线程环境中,一个线程对共享变量的修改可能对其他线程是不可见的。这是因为每个线程有自己的工作内存,线程对变量的修改首先发生在工作内存中,然后被刷新到主内存。其他线程在读取该变量时直接从自己的工作内存中读取,而不是从主内存中读取。 答: 1.主内存与工作内存。 volatile关键字。作用如下: 用于实现内存屏障(Memory Barrier): volatile关键字在读和写操作前后会插入内存屏障,也称为内存栅栏。内存屏障可以分为读屏障和写屏障。 在写入volatile变量时,写屏障会确保所有之前的写操作都完成,然后再执行当前的写操作。这样可以防止指令重排序,确保写操作的原子性。 在读取volatile变量时,读屏障会确保当前线程看到的是最新的值,而不是之前被其他线程修改但还未刷新到主内存的值。 拓展:如果操作 A happens-before 操作 B,那么 A 的执行结果对于 B 是可见的,即 B 能够感知到 A 的影响。volatile关键字可以确保happens-before关系,即对一个volatile变量的写操作先于后续的读操作。 禁止指令重排序 使用CPU屏障指令: 缓存一致性协议: 使用锁机制 (如 synchronized 或 java.util.concurrent 包中的锁ReetrantLock)也能保证可见性。当一个线程获取锁时,它会清空工作内存中的变量,并重新从主内存中读取。 答: 编译器和处理器为了提高性能可能对指令进行重排序。在单线程环境中,指令重排是允许的,因为它不会影响程序的最终执行结果。然而,在多线程环境中,指令重排可能导致共享变量的可见性问题,即一个线程对共享变量的修改对其他线程来说不可见,从而破坏了程序的正确性。 答: 答: 使用 volatile 关键字修饰的变量,对该变量的写操作会在写操作之后插入一个写屏障,确保写操作的结果对其他线程是可见的。同时,对 volatile 变量的读操作会在读操作之前插入一个读屏障,防止在读操作之前的写操作被重排到读操作之后。 使用Synchronized或ReentrantLock解决指令重排 使用final字段解决指令重排问题 工作日每天更新,周末随缘更新。 请关注我,以便及时获取最新内容哦!
“
JMM是什么?
什么是共享变量的可见性?
JMM解决共享变量可见性问题的机制
什么事指令重排?
哪些情况会出现指令重排?
解决指令重排的方法有哪些?
本文由 mdnice 多平台发布
标签:Java,变量,指令,线程,内存,重排,volatile,操作 From: https://blog.csdn.net/zwsfamily/article/details/140668546