Volatile系列(一):Volatile测试案例一可见性

Java并发编程:Volatile关键字的内存可见性测试
文章通过两个测试案例展示了Volatile关键字在Java多线程环境中的作用,特别是在确保内存可见性和禁止指令重排序方面的功能。测试1表明没有Volatile时,线程可能无法感知变量的更新;而在测试2中,添加了Volatile关键字后,所有线程能快速响应变量变化,证明了Volatile的内存可见性效果。

系列文章

Volatile测试案例一可见性

目录

前言

测试1

逻辑

代码

结果

测试2

逻辑

代码

结果

结论

原理探讨(可见性)



前言

多线程是 JAVA 并发编程的主要应用,并发环境能大幅提高应用性能,提高 CPU 使用率,但是并发环境下也引出许多问题。今天咱们主要探讨的就是多线程并发中的一个关键字:Volatile

Volatile 的主要作用:

  • 内存可见性
  • 禁止指令重排序

测试1

逻辑

1.创建一个 BOOL 结束标记,用于结束线程

2.启动多个线程(这里 10 )

3.将结束标记改为 false

代码

public class VolatileExample {

    private static boolean BOOL = true;

    public static void main(String[] args) throws InterruptedException {
        test1();
    }

    private static void test1() throws InterruptedException {
        for (int i = 0; i < 10; i++) {
            new Thread(() -> { while (BOOL) { } },"VolatileThread-"+i).start();
        }
        TimeUnit.MILLISECONDS.sleep(500);
        BOOL = false;
        RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
        String name = runtime.getName();
        System.out.println("当前进程的标识为:" + name);
    }

}

结果

1.通过 java 自带的 jstack 命令,截取 name 中的 @ 前的数字作为 pid(我这里为 11744 )

2.运行 jstack -l pid

3.当前查看到的线程情况(部分线程)

4.观察当前线程可知部分线程未接收到  BOOL 标记的改变而结束线程
 

测试2

逻辑

1.在测试1的逻辑基础上,添加 volatile 关键字

代码

public class VolatileExample {

    private volatile static boolean BOOL = true;

    public static void main(String[] args) throws InterruptedException {
        test1();
    }

    private static void test1() throws InterruptedException {
        for (int i = 0; i < 10; i++) {
            new Thread(() -> { while (BOOL) { } },"VolatileThread-"+i).start();
        }
        TimeUnit.MILLISECONDS.sleep(500);
        BOOL = false;
        RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
        String name = runtime.getName();
        System.out.println("当前进程的标识为:" + name);
    }

}

结果

1.一旦加上 volatile 关键字,当前进行在极短的时间内结束

结论

1.直观来看,volatile 保证了变量的内存可见性,它使得变量能在不同线程中共享

2.这里线程的开始可以使用栅栏统一控制

原理探讨(可见性)

在 JMM 中,可见性问题存在于主内存、CPU内部多级缓存之间。CPU内部多级缓存与主内存是保持同步的,主要通过缓存⼀致性协议(MESI)来解决但是一但涉及一致性,这就相当消耗性能。为此,线程又维护了自己的一份本地缓存,这又导致了新的可见性问题,线程本地缓存与主内存不一致。

Volatile 就是为了解决变量不一致的问题的,也就是可见性问题。其做法是:

  1. 它会强制将对缓存的修改操作立即写入主存;
  2. 如果是写操作,它会导致其他CPU中对应的缓存行无效
  3. 如果是读操作,它发现当前缓存失效后直接去主内存中读取

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值