美文网首页
volatile关键字与内存可见性

volatile关键字与内存可见性

作者: 不知名的蛋挞 | 来源:发表于2018-10-22 09:37 被阅读23次

转载文章:https://www.cnblogs.com/ccfdod/p/6392343.html

举例说明

首先,我们先看一段小程序。

package com.ccfdod.juc;

public class TestVolatile {
    public static void main(String[] args) {
        ThreadDemo td = new ThreadDemo();
        new Thread(td).start();
        
        while(true) {
            if (td.isFlag()) {
                System.out.println("--------------");
                break;
            }
        }
    }
}

class ThreadDemo implements Runnable {
    private boolean flag = false;

    @Override
    public void run() {
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        flag = true;
        System.out.println("flag = " + isFlag());
    }

    public boolean isFlag() {
        return flag;
    }

    public void setFlag(boolean flag) {
        this.flag = flag;
    }
}

程序运行结果:

flag = true

并且程序不会停止。

按理来说,应该会在td线程修改flag值后,主线程会打印出“--------------”,但是为什么没有出现预期效果呢?下面来分析这段程序,涉及到内存可见性问题。

内存可见性问题

当程序运行时,JVM会为每一个执行任务的线程分配一个独立的缓存空间,用于提高效率。

不难理解,程序开始执行时,由于线程td修改flag操作之前,sleep了200ms,td线程和main线程获取到的flag都为false,但为什么td线程将flag改为true后,main线程没有打印出“--------------”呢?原因在于:while(true)是执行效率很高,使得main线程没有时间再次从主存中获取flag的值,因此程序在td线程将flag修改为true后,没有停止运行的原因。其实在while(true)后面稍微延迟一点(比如说,打印一句话),都会使main线程将主存中的flag=true读取。

产生这种情况的原因就在于,两个线程在操作共享数据时,对共享数据的操作是彼此不可见的。

那么为了不让这种问题出现,怎么解决呢?

(1)使用synchronized同步锁

while(true) {
    synchronized (td) {
        if (td.isFlag()) {
            System.out.println("--------------");
            break;        
        }
    }
}

使用synchronized同步锁能保证数据的及时更新。但是效率太低。

(2)使用volatile关键字

当多个线程进行操作共享数据时,可以保证内存中的数据可见。底层原理:内存栅栏。使用volatile关键字修饰时,可理解为对数据的操作都在主存中进行。

private volatile boolean flag = false;

相较于synchronized是一种较为轻量级的同步策略。

相关文章

  • 深入浅出 Java 并发编程 (2)

    本文目录 Java 内存模型与可见性 指令重排序 使用 volatile 关键字保证可见性 使用 synchron...

  • JUC线程高级教程

    JUC 原创者:文思,感谢尚硅谷,资料来源于尚硅谷 目录: 1、volatile关键字与内存可见性 2、原子变量与...

  • volatile什么时候使用

    volatile关键字 我们都知道volatile修饰的变量,保证了数据内存的可见性。 强迫每个线程在读取vola...

  • volatile关键字总结

    volatile保证了线程安全的可见性,是由jvm提供的机制。 java内存模型对volatile关键字定义的特殊...

  • volatile

    目标 1、volatile如何保证内存可见性2、volatile如何禁止指令重排序3、内存屏障4、内存可见性5、关...

  • 小编带您Volatile的详解

    volatile关键字修饰的共享变量主要有两个特点:1.保证了不同线程访问的内存可见性 2.禁止重排序 在说内存可...

  • 深入理解Java多线程中的volatile关键字

    Java 的 volatile关键字对可见性的保证 Java 的 volatile关键字在保证可见性之前的所做的事...

  • Java之Volatile轻量级同步使用

    volatile关键字有两个特性 内存可见性java内存模型规定对于多个线程共享的内存变量,是存储在主内存当中。每...

  • 深度解析volatile—底层实现

    我们都知道,Java关键字volatile的作用 1、内存可见性2、禁止指令重排序 可见性是指,在多线程环境,共享...

  • 1.4 volatile 关键字

    volatile 关键字 volatile关键字是与Java的内存模型有关的,因此需要先了解一下与内存模型相关的概...

网友评论

      本文标题:volatile关键字与内存可见性

      本文链接:https://www.haomeiwen.com/subject/vdywzftx.html