Java多线程(二)Java内存模型

Java 内存模型(JMM)是一种抽象的概念,并不真实存在,它描述了一组规则或规范,通过这组规范定义了程序中各个变量(包括实例字段、静态字段和构成数组对象的元素)的访问方式。JVM中的堆内存用来存储对象实例,堆内存是被所有线程共享的运行时内存区域,因此它存在可见性问题。Java内存模型定义了线程和主存间的抽象关系:线程之间的共享变量存储在主存中,每个线程有一个私有的本地内存,本地内存中存储了该线程共享变量的副本。需要注意的是本地内存是Java内存模型的一个抽象概念,并不真实存在,它涵盖了缓存、写缓冲区、寄存器等区域。Java内存模型的抽象示意图如下所示:

线程A与线程B要通信的话,要经历下面两个步骤:

  1. 线程A把线程A本地内存中更新过的内存共享变量刷新到主存;
  2. 线程B到主存中取线程A之前更新过的共享变量。

所以我们在执行下面语句:

int i = 0;

语句所在的线程会对变量i所在的缓存进行赋值操作,然后再写入主存中,而不是直接将数值0写入主存。

为了有个直观的感受,我们用一段代码来实现一下。先定义一个类VolatileDemo,包含一个running字段和一个stop方法:

public class VolatileDemo {
    public boolean running = true;

    public void stop() {
        running = false;
    }
}
public static void main(String[] args) {
        VolatileDemo demo = new VolatileDemo();
        System.out.println(Thread.currentThread().getName() + " start");
        new Thread(() -> {
            System.out.println(Thread.currentThread().getName() + " start");
            while (demo.running) {

            }
            System.out.println(Thread.currentThread().getName() + " end");
        }).start();

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        demo.stop();
        System.out.println(Thread.currentThread().getName() + " end");
    }

我们在main方法,即主线程中创建VolatileDemo对象实例,然后新创建一个子线程,进入while循环不断的判断running属性。我们让主线程sleep1000毫秒,然后执行stop更新running的值为false,按正常逻辑如果running = false的话,子线程就会执行完,打印end,然后整个程序执行完毕。我们运行程序看一下:

发现子线程并没有打印end,并且程序一直在运行,没有结束退出。说明主线程更新的running = false,子线程并不知道。

示例代码已上传Github

学习更多知识,请关注我的个人博客:droidYu

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值