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

在构造函数中使用同步块有什么用?

通啸
2023-03-14

我们不能使构造函数同步,但可以在构造函数内部编写同步。在什么情况下会有这样的要求?我很开心。

package com.simple;
public class Test {
    public Test() {
        synchronized (this) {
            System.out.println("I am called ...");
        }
    }

    public static void main(String[] args) {
        Test test=new Test();   
        System.out.println(""+test);
    }

    @Override
    public String toString() {
        return "Test []";
    }
}

共有3个答案

岳阳文
2023-03-14

它可以用来确保构造函数中非最终字段的安全发布。

public class Test {
    int a;
    public Test() {
        synchronized (this) {
            a = 5;
        }
    }

如果另一个线程接收到一个类型为Test的对象,并且它也在该Test实例上同步,那么这将在构造函数中的同步的块的结尾和的开头之间创建一个发生前关系另一个线程中同步的块:

public class InOneThread {
    public void run() {
        InAnotherThread.test = new Test();
    }
}

public class InAnotherThread {
     public static Test test;

     public void run() {
         if (test == null) {
             // Because assignment to `test` wasn't safely published, the
             // field could be null even if it was assigned "earlier" in real
             // time.
             return;
         }
         synchronized(test) {
             System.out.println(test.a); 
             // If no more modifications were made to 'a', this prints 5
             // (guaranteed). Without the synchronized blocks, this could 
             // print 0 (zero) or 5.
         }
     }
}

然而在实践中,这几乎从来没有用过,因为需要同步机制来安全地将Test的实例从一个线程传递到另一个线程,并且同步机制本身几乎肯定已经在线程之间引入了发生前关系。

尽管如此,它还是可以在一些高度特定的并发组件中使用。

罗鸿福
2023-03-14

this上同步将是一种不良做法的迹象,因为这意味着你正在从构造函数中泄漏this:这是在同一个对象上同步其他代码的唯一方法。

然而,在其他一些公共锁上进行同步可能是合法的:我的构造函数确实涉及调用一些需要这种同步的代码。

佴涵蓄
2023-03-14

您可以在构造函数中启动一个新线程。这将是非常不寻常的——当然在你提供的代码中这将是毫无意义的——但它可能会发生。

语言通常不会试图找到你能做的每一件毫无意义的事情——这会导致一个非常复杂的语言规范。语言使用者也必须有一定程度的思考。。。

 类似资料:
  • 问题内容: 根据Java语言规范,无法将构造函数标记为已同步,因为其他线程在创建该对象的线程完成之前无法看到正在创建的对象。这似乎有些奇怪,因为在构造对象时,我确实可以让另一个线程查看该对象: 我知道这是一个非常人为的示例,但从理论上讲,似乎有人可以提出一个更现实的案例,在该案例中,标记构造函数为同步状态是合法的,以防止此类线程的竞争。 我的问题是:Java是否有理由特别禁止在构造函数上使用syn

  • 问题内容: 某个地方的人告诉我Java构造函数是同步的,因此在构造过程中不能同时访问它,而我在想:是否有构造函数将对象存储在映射中,而另一个线程在构造之前从该映射检索它完成后,该线程是否会阻塞,直到构造函数完成? 让我用一些代码演示: 假设put / get是地图上唯一的操作,因此我不会通过迭代之类的方法来获取CME,并尝试在此忽略其他明显的缺陷。 我想知道的是,如果另一个线程(显然不是构造该对象

  • 问题内容: 众所周知,您可以使用类型参数在Java中创建一个通用类: 但是,您也可以使用泛型 构造函数 ,这意味着显式接收其自己的泛型类型参数的构造函数,例如: 我正在努力了解用例。这个功能让我做什么? 问题答案: 这个功能让我做什么? 它至少可以让您完成 三 件事,而这 三 件事是您无法做到的: 表达参数类型之间的关系,例如: } <撤回> 正如@Lino首先观察到的那样,它使您可以表达参数必须

  • 问题内容: 从文档中学习React 并遇到以下示例: 根据Mozilla的说法,super允许您在构造函数中使用。是否有其他原因可以单独使用(我知道也可以访问父类的方法),但是使用React时,是否还有其他仅通过自身调用的用例? 问题答案: 仅在具有构造函数的React组件内部被调用。例如,以下代码不需要超级: 但是,如果我们有一个构造函数,那么它是强制性的: 之所以不能被允许之前的原因是因为未调

  • 类有2个构造函数 oracle的第二个构造函数的描述如下 谁能解释一下?

  • 问题内容: 为什么不能和这两个一起在构造函数中使用? 合并这样的东西的原因是什么? 问题答案: 将在同一类中调用另一个构造函数,而将调用超级构造函数。如果构造函数中没有,则编译器将隐式添加一个。 因此,如果两者都允许,您最终可能会两次调用构造函数。 示例(不要在参数中寻找含义): 现在,如果调用,将调用以下构造函数: 更新 : 如果您能够使用并且可能会得到如下结果: ( 注意 :这是为了说明 如果