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

我们不能使构造函数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 []"; } } 

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

语言通常不会试图找到你可能做的每件事都没有意义 – 它会导致非常复杂的语言规范。 语言用户也必须有一定程度的思考……

同步this将是一个不好的做法的标志,因为它意味着你从构造函数中泄露了this :这是你可以让一些其他代码在同一个对象上同步的唯一方法。

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

可能是您正在更改多个线程访问的构造函数中的一些常见数据。 虽然更好和简单的方法将是首选。

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

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

例如:

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

在此示例中,如果在someService调用criticalSection() ,则将强制您等待,直到构造函数中的synchronized块完成。

但同样,不推荐这样做,你永远不应该允许this逃避构造函数。

据我所知,如果你处理构造函数中的静态字段,它可能是至关重要的。 当对象正在构建时,只有创建它的线程才能访问该对象,但是如果构造函数中的静态字段值发生更改,则可能是一个问题,因为两个不同的线程可以同时创建同一类的对象,从而导致冲突相关到静态字段。 但不确定使用进行锁定是否是个好主意

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

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

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

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

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