Volatile总结

本文介绍了Java内存模型,强调了Volatile关键字的作用。Volatile确保了多线程环境下的线程可见性,防止指令重排序,但不保证原子性。通过MESI协议,Volatile在写操作时会加锁并通知其他CPU缓存失效,保证数据一致性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Volatile总结

1.Java内存模型

java内存模型中 所有变量都存储在主内存(虚拟机内存)《主要指共享变量》,每个线程有着自己独有的工作内存,工作内存中保存了该线程使用的变量,这些变量来自主内存中变量的副本拷贝。线程对变量的所有操作都必须在工作内存中进行,不能直接读写主存中的变量,不同线程之间的工作内存时相互独立的,不可以访问其他线程的工作内存。

在线程工作时,把需要的变量从主内存中拷贝到自己的工作内存

在这里插入图片描述

当一个线程要使用一个共享变量时,并不会直接使用,而是使用它的一个副本,然后交互副本值 ,

当出现JMM的缓存不一致时可以总线加锁 也可以使用 MESI缓存一致性协议

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fAVphV96-1616324208923)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210311155347951.png)]

java 中volatitle 就相当于使用了MESI缓存一致性

下面代码展示 volatile 的作用 -boolean类型的开关

/**
 * @Author: hqx
 * @Description:
 * @Date: Created in 12:01 2021/3/21
 */

/**
 * @author Administrator
 * @create 2021-03-21 12:01
 * @desc
 **/
public class volatilettest {
    //使用volatile 作为 boolean类型 开关
    private static boolean flag1 = false;
    private static volatile boolean flag2 = false;

    public static void main(String[] args) throws InterruptedException {
        volatilettest vo = new volatilettest();
        new Thread(() -> {
            //flag为false 时一直循环
            System.out.println("111工作中---");
            while (!flag1) {
            }
            System.out.println("111工作结束--");
        }).start();


        new Thread(() -> {
            //flag为false 时一直循环
            System.out.println("222工作中---");
            while (!flag2) {
            }
            System.out.println("222工作结束--");
        }).start();
        //主线程
        Thread.sleep(1000);

        vo.change1();
        vo.change2();
    }

    public void change1() {
        System.out.println("1进入改变函数");
        flag1 = true;
        System.out.println("1改变完成-");
    }

    public void change2() {
        System.out.println("2进入改变函数");
        flag2 = true;
        System.out.println("2改变完成-");
    }
}

在这里插入图片描述

2.volatitle 原理实现

会在汇编语言中加入一个lock指令,该指令会将当前处理器缓存行的数据立刻写回到系统的内存中,并且这个写回内存的操作还会引起在其他cpu里缓存了该内存地址的数据无效**(MESI协议)cpu总线嗅探机制**

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vMkuSjeK-1616324208941)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210311163416047.png)]

工作内存会与主内存进行数据交互读写,主要由8种操作进行:

lock(锁定):作用于主内存变量,把一个变量标识为一条线程独占

unlock(解锁):

read(读取):作用于主内存变量,将一个变量值从主内存传输到线程的工作内存

load(载入):作用于工作内存变量,他把通过read操作从主内存中得到的变量值放入工作内存的变量副本中

use(使用):作用域工作内存变量,将工作内存中的一个变量值传递给执行引擎,每当虚拟机遇到一个要给变量赋值的字节码执行时会使用这个操作

assign(赋值):作用于工作内存的变量,它把一个从执行引擎处接收到的值赋给工作内存中的一个变量,每当虚拟机遇到一个给变量赋值的字节码时就会执行这个操作

stroe(存储):作用域工作内存变量,将工作内存中的一个变量的值传送到主内存中

write(写入):作用域主内存变量 ,他把通过store操作从工作内存中读取的变量值放入主内存的变量中

上述8个操作存在约束:

1.read+load 与 store+write 可以成对出现

2.不允许线程丢弃它最近的assign操作 ,即变量在工作内存中改变之后,必须同步写回主内存

3.不允许线程把没有经过assign操作的变量写回到主存

4.一个新的变量只能在主内存中诞生,不允许在工作内存中国使用未经初始化的变量,即在进行use 之前必须load 在store之前必须assign

5.对一个变量执行lock操作

下图为上面boolean开关的实例的一个过程演示
在这里插入图片描述

通过read 读取主内存中的变量并传送到工作内存,load将read获取的值赋值给工作内存中对应的变量,use读取initFlag的值给到执行引擎,assign将更新后的值写回到工作内存中的initFlag 在通过store,write写回到主内存

volatitle 会在store和write这个过程中加锁,并且在触发cpu嗅探机制

volatitle作用

在通过store,write写回到主内存

volatitle 会在store和write这个过程中加锁,并且在触发cpu嗅探机制

[外链图片转存中…(img-RzVV6eiC-1616324208947)]

volatitle作用

线程可见性,可以禁止指令重排 ,保证顺序性。不具备线程安全性,原子性

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值