3

我正在阅读“Java Concurrency in Practice”并尝试编写一段代码来说明第 3.5.1 章中作为示例介绍的类确实会引入问题。

public class Holder {
    public int n;

    public Holder(int n) {
        this.n = n;
    }

    public void assertSanity() {
        if (n != n) {
            throw new AssertionError("sanity check failed!!");
        }
    }
}

据说如果按以下方式使用(我相信这是关于该字段是公共的事实,可能会发生并发问题。

public Holder holder;
public void initialize() {
    holder = new Holder(42);
}

所以我想出了这段代码,看看是否有任何不好的事情发生。

public class SanityCheck {

    public Holder holder;

    public static void main(String[] args) {

        SanityCheck sanityCheck = new SanityCheck();
        sanityCheck.runTest();

    }

    public void runTest() {
        for (int i = 0; i < 100; i++) {
            new Thread() {
                @Override
                public void run() {
                    while (true) {
                        if (holder != null) {
                            holder.assertSanity();
                        }

                        try {
                            Thread.sleep(1);
                        } catch (InterruptedException e) {
                        }
                    }
                }
            }.start();
        }

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
        }

        initialize();

    }

    public void initialize() {
        holder = new Holder(42);
    }
}

但是没有任何不好的事情发生,没有抛出 AssertionError 。

你能帮我弄清楚为什么这段代码不会阻止任何东西吗?

提前感谢您的宝贵时间。

4

3 回答 3

3

代码不是线程安全的并且可能产生并发问题的事实并不意味着它会这样做

Java 内存模型 (JMM) 说明了程序在正确同步时必须如何运行。但它并没有说明一个程序在不正常的情况如何表现。

例如,强制执行顺序一致性的 JVM 将与 JMM 兼容,并且不会发生并发问题。

在您的具体示例中,x86/hostpot 组合不太可能中断。

于 2013-07-18T16:14:31.790 回答
2

据说如果以休闲方式使用(我相信这是关于该领域是公共的事实,可能会发生并发问题。

问题可能会发生,但不能保证一定会出现任何问题。

如果您使用的是 Oracle JVM,AFAIK 会将互操作代码访问视为易失性。只有在您编译了构造函数和检查器后,您才会发现问题。即使那样,我怀疑你也会有困难。

于 2013-07-18T16:14:52.143 回答
0

你不应该改变的价值n导致某些东西破坏吗?以目前的形式,我看不到AssertionError将如何抛出,无论并发问题如何。

我期待这样的事情:

if (holder != null) {
    holder.n = holder.n - 1;
    holder.assertSanity();
}
于 2013-07-18T17:15:22.683 回答