未初始化的对象泄漏到另一个线程,尽管没有代码明确泄漏吗? [英] Uninitialized object leaked to another thread despite no code explicitly leaking it?

查看:175
本文介绍了未初始化的对象泄漏到另一个线程,尽管没有代码明确泄漏吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

让我们看看这个简单的Java程序:

  import java.util。*; 

class A {
static B b;
static class B {
int x;
B(int x){
this.x = x;
}
}
public static void main(String [] args){
new Thread(){
void f(B q){
int x = qx;
if(x!= 1){
System.out.println(x);
System.exit(1);
}
}
@Override
public void run(){
while(b == null);
while(true)f(b);
}
} .start();
for(int x = 0 ;; x ++)
b = new B(Math.max(x%2,1));
}
}

主线程 p>

主线程使用 x 设置创建 B 的实例到1,然后将该实例写入静态字段 Ab


$ b

轮询线程

它发现 Abx 不是1。



?!?

一半的时间,它在一个无限循环,如预期,但一半的时间,我得到这个输出:

  $ java A 
0

为什么轮询线程能够请参阅 B x 未设置为1?



< hr>

x%2 而不仅仅是 x






我在linux x64上运行openjdk 6.

解决方案

这是我的想法:因为 b不是最终,编译器可以自由地重新排序操作, ?因此,这基本上是一个重新排序问题,因此,一个不安全的发布问题将变量标记为final将修复这个问题。



更多或较少,则与中所提供的示例相同Java内存模型文档



真正的问题是如何做到这一点。我也可以在这里推测(因为我不知道如何编译器将重新排序),但也许B的引用写入主内存(在其中它是可见的其他线程)之前写入x发生。在这两个操作之间读取发生,因此零值


Let's see this simple Java program:

import java.util.*;

class A {
    static B b;
    static class B {
        int x;
        B(int x) {
            this.x = x;
        }
    }
    public static void main(String[] args) {
        new Thread() {
            void f(B q) {
                int x = q.x;
                if (x != 1) {
                    System.out.println(x);
                    System.exit(1);
                }
            }
            @Override
            public void run() {
                while (b == null);
                while (true) f(b);
            }
        }.start();
        for (int x = 0;;x++)
            b = new B(Math.max(x%2,1));
    }
}

Main thread

The main thread creates an instance of B with x set to 1, then writes that instance to the static field A.b. It repeats this action forever.

Polling thread

The spawned thread polls until it finds that A.b.x is not 1.

?!?

Half the time it goes in an infinite loop as expected, but half the time I get this output:

$ java A
0

Why is the polling thread able to see a B that has x not set to 1?


x%2 instead of just x is here simply because the issue is reproducible with it.


I'm running openjdk 6 on linux x64.

解决方案

Here is what I think: because b is not final, the compiler is free to reorder the operations as it likes, right? So this, fundamentally is a reordering issue and as a result a unsafe publication issue Marking the variable as final will fix the problem.

More or less, it is the same example as provided here in the Java memory model docs.

The real question is how is this possible. I can also speculate here (since I have no idea how the compiler will reorder), but maybe the reference to B is written to the main memory (where it is visible to the other thread) BEFORE the write to x happens. In between these two operations the read happens, thus the zero value

这篇关于未初始化的对象泄漏到另一个线程,尽管没有代码明确泄漏吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆