java - 我想测试延迟初始化是否是线程安全的

标签 java thread-safety race-condition

我想测试延迟初始化是否是线程安全的,所以我的代码如下:

package LazyInit;

import java.util.Random;

public class UnThreadSafeLazyInit {

    private ExpensiveObject instance = null;

    public ExpensiveObject getInstance() {
        if (null == instance) {
            instance = new ExpensiveObject();
        }
        System.out.println("instance=" + instance);
        return instance;
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub


        for (int i = 0; i < 5; i++) {
            UnThreadSafeLazyInit  init = new UnThreadSafeLazyInit();
            Task t1 = init.new Task();
            Task t2 = init.new Task();
            t1.start();
            t2.start();
            try {
                Thread.sleep(4000);
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println(t1.getInstance() == t2.getInstance());
        }
    }

    static class ExpensiveObject {

    }

    class Task extends Thread {

        private ExpensiveObject instance = null;
        private Random rand = new Random(47);

        public void setInstance () {
            this.instance = UnThreadSafeLazyInit.this.getInstance();
        }

        public ExpensiveObject getInstance() {
            return instance;
        }

        @Override
        public void run() {
            // TODO Auto-generated method stub

            try {
                Thread.sleep(rand.nextInt(1000));
            } catch (Exception e) {
                e.printStackTrace();
            }
            setInstance();
        }
    }

}

在我的代码中,每次new两个Thead任务都会调用public ExpenseObject getInstance(),以证明这两个实例自竞争条件以来,可能对 ExpenseObject 的引用不同。 当我运行它时,它总是通过 t1.getInstance() == t1.getInstance() 返回 true。 据我所知,如果我不同步函数public ExpenseObject getInstance(),它可能会返回 false,因为延迟初始化中存在竞争条件。 我需要找出哪个代码是错误的。 谢谢。

最佳答案

仅通过检查代码,它不是线程安全的。您遇到的问题是,许多毫秒的延迟对于计算机来说是一个巨大的时间,并且您非常非常不可能在这种类型的测试中发现问题。

例如,更新 volatile 字段与其他线程可见之间的典型延迟约为 5 纳秒。大约这么长时间以来,您的解决方案都不是线程安全的。您最多需要等待 1,000,000,000 纳秒才能查看是否遇到问题。

这就像试图看看持续 5 秒的烟花是否燃放,但闭上眼睛 317 年后才得出没有烟花的结论。

关于java - 我想测试延迟初始化是否是线程安全的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16505412/

相关文章:

java - 如何构建在 java 中动态调整大小的布局?

multithreading - 通用线程安全属性

javascript - ReadStream和WriteStream到nodejs中的同一个文件

c++ - 在 C++ 中递增和递减全局变量时的竞争条件

java - 如何在jsp中保留变量onchange?

java - Realm 数据库中的搜索操作速度

java - 如何从 Urban code Deploy 工作区获取文件

java - 运行一个线程一段时间,如果时间到了就杀掉它

multithreading - 实现线程安全

c++ - x86 上的竞争条件