我们不能创建构造函数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 []";
}
}
答案 0 :(得分:11)
好吧,你可以在构造函数中启动一个新线程。这将是非常不寻常的 - 当然在您提供的代码中它将毫无意义 - 但它可能会发生。
语言通常不会尝试找到你可能做的每件事都没有意义 - 它会导致非常复杂的语言规范。语言使用者也必须有一定程度的思考......
答案 1 :(得分:6)
在this
上进行同步将是不良做法的标志,因为这意味着您将this
从构造函数中泄露出来:这是您可以在同一对象上同步其他代码的唯一方法
然而,在其他一些常见的锁上同步可能是合法的:构造函数确实涉及调用一些需要这种同步的代码。
答案 2 :(得分:0)
可能是您正在更改多个线程访问的构造函数中的一些常见数据。虽然更好,更简单的方法是首选。
答案 3 :(得分:0)
在正常情况下,你没有理由这样做。
但是,如果你让this
引用“转义”构造函数(当然这是不好的做法),那么你可能想强制客户端代码在调用其他代码之前等待synchronized块完成操作
例如:
class C {
public C() {
// ....
synchronized(this) {
someService.doSomethingWith(this);
// some other critical stuff...
}
}
public synchronized void criticalSection() {
// ...
}
}
在这个例子中,如果你在criticalSection()
内调用someService
,你将被迫等到构造函数中的synchronized块完成。
但是,不建议这样做,你绝不允许this
转义构造函数。
答案 4 :(得分:0)
据我所知,如果你处理构造函数中的静态字段,那么它是至关重要的。当对象正在构建时,只有创建它的线程才能访问此对象,但是如果构造函数中的静态字段值发生更改,则可能是一个问题,因为两个不同的线程可以同时创建同一类的对象,从而导致冲突相关到静态字段。但不确定使用 this 来锁定
是否是个好主意答案 5 :(得分:0)
它可用于确保在构造函数中安全发布非final字段。
public class Test {
int a;
public Test() {
synchronized (this) {
a = 5;
}
}
如果另一个线程收到一个Test类型的对象,并且它也在Test
的那个实例上同步,那么这会在构造函数中synchronized
块的结尾之间创建一个before-before关系,以及另一个帖子中synchronized
块的开头:
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的实例从一个线程传递到另一个线程,并且同步机制本身几乎肯定已经引入了线程之间的先发生关系。 / p>
它仍然可以在一些高度特定的并发组件中使用。
答案 6 :(得分:0)
我认为Java灵活性可以做到这一点,因为在构造函数内部,您几乎可以将所有内容作为常规方法(Methods vs Constructors in Java)进行,但是如果这样做的话,这是一种不好的做法。 这是一个很好的实践问题,我们不应该在构造函数中使用同步块,在任何情况下都不能在构造函数中做得更好。