zoukankan      html  css  js  c++  java
  • java volatile 实现变量可见性

    java volatile 实现变量可见性

    volatile 本意是易变的,多变的,用来解决变量可见性问题,什么是变量可见性问题?先看一下变量在计算机内部第一次加载和写入过程:

    此时,内存和寄存器中v都是101,再进行计算时时直接从register中读取而不是memroy来提高速度。这在单核CPU中没毛病,如果是多核CPU中,变量v在各自寄存器中都有值了,即使内存中的变量v更新了它还是从寄存器的缓存中读取,就会导致程序运行结果不符合预期,变量的可见性,指的是它被修改后其他线程可以立即看到最新结果的能力。使用一个用例来复现这种现象:

    1. 创建一个全局变量running
    2. 创建一个名为ObserveThread子线程,让它不停观察running的值(预期它在不停地从寄存器中读值)
    3. 在主线程中修改running的值,观察子线程/和主线程中的值是否发生变化(预期子线程的没变,主线程的变了)

    代码:

    package juc.test.sharememroy;
    
    public class StaticVolatileTest {
    
        static /*volatile*/ boolean running = true;
    
        public static void main(String[] args) {
    
            new Thread("ObserveThread"){
                @Override
                public void run() {
                    System.out.println("thread start");
                    while (running){}
                    System.out.println("thread end");
                }
            }.start();
    
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            running = false;
            System.out.println("main thread end, running = " + running);
        }   
    }
    

    3秒后线程没有结束,查看JVM中的线程状态发现ObserveThread还在Running:

    控制台输出结果:

    thread start
    main thread end, running = false
    

    可以说明ObserverThread 线程没读取到主线程修改后的值,而是从它的缓存中读值,只要将

    static /*volatile*/ boolean running = true;
    

    修改为:

    static volatile boolean running = true;
    

    问题就解决了,输出就变成:

    thread start
    main thread end, running = false
    thread end
    

    volatile是使用缓存一致性协议实现的,对于可能频繁修改的变量,每次不从寄存器而是从内存中读取,降低速度来保证可见性。

  • 相关阅读:
    C#(64位系统) 解决"未能加载文件或程序集,或它的某一个依赖项..."
    C#匿名方法与Delegate类型转换错误
    记录C#错误日志工具
    C# 引用访问权限,很多老手都不懂
    .NET基础之自定义泛型
    C# Socket学习笔记一
    .Net垃圾收集机制—了解算法与代龄
    审计系统---堡垒机项目之环境准备
    审计系统---堡垒机项目之表结构设计
    审计系统---堡垒机python下ssh的使用
  • 原文地址:https://www.cnblogs.com/oaks/p/13418173.html
Copyright © 2011-2022 走看看