8

我们不能制作构造函数synchronized,但可以在构造函数中编写synchronized它。在什么情况下会出现这样的要求?我很开心。

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 []";
    }
}
4

7 回答 7

10

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

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

于 2013-02-22T10:17:07.830 回答
6

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

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

于 2013-02-22T10:18:26.107 回答
1

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

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

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

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 的实例从一个线程传递到另一个线程,并且同步机制本身几乎肯定已经在线程之间引入了先发生关系。

它仍然可以在一些高度特定的并发组件中使用。

于 2016-01-08T08:47:40.960 回答
0

可能是您正在更改由多个线程访问的构造函数中的一些公共数据。尽管最好使用更好和简单的方法。

于 2013-02-22T10:21:08.193 回答
0

在正常情况下,您应该没有理由这样做。

但是,如果您让this引用“转义”构造函数(这当然是不好的做法),那么您可能希望强制客户端代码在调用其他操作之前等待同步块完成。

例如:

class C {
    public C() {
        // ....
        synchronized(this) {
            someService.doSomethingWith(this);
            // some other critical stuff...
        }
    }

    public synchronized void criticalSection() {
        // ...
    }

}

在这个例子中,如果你调用criticalSection()inside someService,你将被迫等到构造函数中的同步块完成。

但同样,不建议这样做,您永远不应该允许this逃避构造函数。

于 2013-02-22T10:23:27.783 回答
0

我认为 Java 的灵活性允许这样做,因为在构造函数中,您几乎可以像普通方法一样做所有事情(Java 中的方法与构造函数),但是如果我们这样做,这是一种不好的做法。这是一个很好的做法,我们不应该在构造函数中使用同步块,在构造函数中没有更好的做法。

于 2019-11-25T11:24:37.170 回答
0

据我了解,如果您在构造函数中处理静态字段,这可能很关键。当对象正在构建时,只有创建它的线程才能访问该对象,但是如果构造函数中的静态字段值发生更改,这可能会成为问题,因为两个不同的线程可以同时创建同一类的对象,从而导致相关的冲突到静态字段。但不确定将其用于锁定是否是个主意

于 2015-09-18T20:18:31.820 回答