当前位置: 首页 > 知识库问答 >
问题:

singleton调用的构造函数中的synchronized block会同步Java中的线程吗?

阳兴文
2023-03-14
import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class SingletonPattern {
    public static void main(String[] args) throws InterruptedException, IOException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        final TestClass[] i1 = {null};
        final TestClass[] i2 = {null};

        final Constructor<TestClass> constructor = TestClass.class.getDeclaredConstructor();
        constructor.setAccessible(true);

        Thread t3 = new Thread() {
            @Override
            public void run() {
                try {
                    i1[0] = constructor.newInstance();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        };
        Thread t4 = new Thread() {
            @Override
            public void run() {
                try {
                    i2[0] = constructor.newInstance();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        };

        t3.start();
        t4.start();
        t3.join();
        t4.join();
        System.out.println((i1[0] == i2[0]) + "  " + i2[0].equals(i1[0]));
    }


    static class TestClass implements Cloneable, Serializable{
        private static TestClass instance;
        private static final Object obj = new Object();

        private TestClass() {
            synchronized (TestClass.class) {
                for (int i = 0; i < 100000; i++) ;
                if (instance != null) {
                    throw new RuntimeException("Operation not allowed. Use getInstance method.");
                }
            }
        }

        public static TestClass getInstance() {
            if (instance == null) {
                synchronized (TestClass.class) {
                    if (instance == null) {
                        for (int i = 0; i < 100000; i++) ;
                        instance = new TestClass();
                    }
                }
            }
            return instance;
        }

        public static TestClass getClone() {
            try {
                return (TestClass) instance.clone();
            } catch (CloneNotSupportedException e) {
                e.printStackTrace();
            }
            return null;
        }

        @Override
        protected Object clone() throws CloneNotSupportedException {
            return instance;
        }

        private Object readResolve() {
            return getInstance();
        }
    }
}

共有1个答案

壤驷安和
2023-03-14

如果构造函数中的synchronized块真的同步了,那么我应该会看到一些异常。但这并没有发生。

构造函数方法中,instance!=null将始终返回false,因为从未分配instace

您可以添加instance=this,在这种情况下,只有一个线程可以通过反射构造实例,其他线程将获得异常:

       private TestClass() {
            synchronized (TestClass.class) {
                for (int i = 0; i < 100000; i++) ;
                if (instance != null) {
                    throw new RuntimeException("Operation not allowed. Use getInstance method.");
                }
                instance = this;
            }
        }
 类似资料:
  • 问题内容: 某个地方的人告诉我Java构造函数是同步的,因此在构造过程中不能同时访问它,而我在想:是否有构造函数将对象存储在映射中,而另一个线程在构造之前从该映射检索它完成后,该线程是否会阻塞,直到构造函数完成? 让我用一些代码演示: 假设put / get是地图上唯一的操作,因此我不会通过迭代之类的方法来获取CME,并尝试在此忽略其他明显的缺陷。 我想知道的是,如果另一个线程(显然不是构造该对象

  • 问题内容: 对不起任何较小的语法错误或其他错误,我正在使用Jitsi模块进行此操作,并且对Java不太熟悉,因此想确认正在发生的事情以及为什么以及如何对其进行修复。 使用按名称加载类方法创建类B的实例时,应用程序正在执行此操作: 在类B中调用重写的load() 初始化变量(根据调试器调用“私有字符串testString = null”),将其无效。 这是预期的Java行为吗?是什么原因造成的?它是

  • 问题内容: 嘿,我对函数的原型和固有性有疑问。您能否解释一下如何从构造函数返回arr并将此arr添加到原型中? 并且在this.arr中是未定义的。有角度的工厂以及前端和后端之间的连接 问题答案: 将异步操作放入构造函数中特别困难。这有几个原因: 构造函数需要返回新创建的对象,因此它不能返回将告诉您异步操作何时完成的承诺。 如果在构造函数内进行异步操作以设置一些实例数据,并且构造函数返回对象,则调

  • 这是我在编写java时从未考虑过的,因为我使用这个模式时没有任何问题: 这样做效果很好,因为重写的函数不依赖于任何未初始化的数据,但是它们对于每个派生的都是唯一的(因此需要抽象)。这在科特林也有效,但它仍然给出了警告。 那么在Java/Kotlin中这种做法是不是很糟糕呢?如果有,我该如何改进?是否可以在kotlin中实现而不被警告在构造函数中使用非final函数? 一个可能的解决方案是将行移动到

  • 如果我决定使用一个非线程安全的集合并同步它的访问,我是否需要同步构造函数中的任何突变?例如,在下面的代码中,我知道对列表的引用在构造后对所有线程都是可见的,因为它是最终的。但我不知道这是否构成安全发布,因为构造函数中的add没有同步,而且它正在ArrayList的elementData数组中添加一个引用,这是非最终的。

  • 问题内容: 我正在尝试创建一个将字段作为参数的构造函数,然后将其放入存储在超类中的字段中。这是我正在使用的代码 在超类中,我用 我有一个访问器方法 我收到一个错误“ 味道在超类中具有私有访问权 ”,但是我认为这无关紧要,因为我正在调用将其返回到字段的访问器方法? 问题答案: 您应该做什么: 在您的超类中添加一个构造函数: 在Crisps类中: 注释 对您的问题的一些评论: “在超类中,我已经用”