加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

Java内存模型中本地最终变量的语义?

发布时间:2020-12-14 06:01:13 所属栏目:Java 来源:网络整理
导读:以下代码有时会在我的 Windows-PC和Mac上打
以下代码有时会在我的 Windows-PC和Mac上打印“valueWrapper.isZero()”,
两者都以服务器模式运行JVM.
好的,这是因为值字段在ValueWrapper类中不是final,
所以某些线程可能会看到陈旧值为0.
public class ConcurrencyApp {
    private final Random rand = new Random(System.currentTimeMillis());
    private ValueWrapper valueWrapper;

    private static class ValueWrapper {
       private int value;

        public ValueWrapper(int value) {
            this.value = value;
        }

        public boolean isZero() {
            return value == 0;
        }
    }

    private void go() {
        while (true) {
            valueWrapper = new ValueWrapper(randomInt(10,1024));
            Thread thread = new Thread(new Runnable() {

                @Override
                public void run() {
                    if (valueWrapper.isZero()) {
                        System.out.println("valueWrapper.isZero()");
                    }
                }
            });
            thread.start();
        }
    }

    private int randomInt(int min,int max) {
        int randomNum = rand.nextInt((max - min) + 1) + min;
        return randomNum;
    }

    public static void printVMInfos() {
        String vmName = System.getProperty("java.vm.name");
        System.out.println("vm name: " + vmName);
        int cores = Runtime.getRuntime().availableProcessors();
        System.out.println("available cores: " + cores);
    }

    public static void main(String[] args) {
        ConcurrencyApp app = new ConcurrencyApp();
        printVMInfos();
        app.go();
    }
}

但是下面的修改呢,这里我使用了一个局部最终变量:

private void go() {
    while (true) {
        final ValueWrapper valueWrapper = new ValueWrapper(randomInt(10,1024));
        Thread thread = new Thread(new Runnable() {

            @Override
            public void run() {
                if (valueWrapper.isZero()) {
                    System.out.println("valueWrapper.isZero()");
                }
            }
        });

        thread.start();
    }
}

看起来现在没有线程看到过时的值为0.
但这是由JMM保证的吗?
在规范中简要介绍并不能说服我.

解决方法

我正在解决格雷没有提到的一点,但我会接受他,因为他的回答是正确的

The following code sometimes prints “valueWrapper.isZero()” on my Windows-PC and a Mac,both running their JVM in server mode…. It looks like that now no thread sees a stale value of 0. But is this
guaranteed by the JMM? A brief look in the spec doesn’t convinced me.

你看到valueWrapper.isZero()返回true的原因有时是因为在调用start之后和运行之前valueWrapper正在改变布尔测试.如果您只创建了一个实例,那么Gray总是不会为零.

最终的ValueWrapper valueWrapper = new ValueWrapper(randomInt(10,1024));一直工作是因为字段是本地的线程(和方法),本地对象和匿名内部类的语义是将原始引用复制到类实例中.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读