为什么Java构造函数不能同步? [英] Why can't Java constructors be synchronized?

查看:151
本文介绍了为什么Java构造函数不能同步?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据 Java语言规范,构造函数不能被标记为同步,因为其他线程不能看到正在创建的对象,直到创建它的线程完成它。这看起来有点奇怪,因为我可以确实有另一个线程查看对象,同时它正在构建:

According to the Java Language Specification, constructors cannot be marked synchronized because other threads cannot see the object being created until the thread creating it has finished it. This seems a bit odd, because I can indeed have another thread view the object while it's being constructed:

public class Test {
    public Test() {
       final Test me = this;
       new Thread() {
           @Override
           public void run() {
               // ... Reference 'me,' the object being constructed
           }
       }.start();
    }
}

我知道这是一个非常有用的例子,似乎在理论上,有人可能想出一个更现实的情况下,标记构造函数同步是合法的,以防止比赛与这样的线程。

I know that this is a pretty contrived example, but it seems in theory that someone could come up with a more realistic case where marking the constructor synchronized would be legitimate in order to prevent races with threads like this one.

我的问题是这样的:有一个原因,Java会明确禁止在构造函数的同步修饰符?也许我上面的例子是有缺陷的,或者也许真的没有理由,这是一个任意的设计决定。在任何一种情况下,我真的很好奇,很想知道答案。

My question is this: is there a reason that Java would specifically disallow the synchronized modifier on a constructor? Perhaps my above example is flawed, or perhaps there really is no reason and it's an arbitrary design decision. In either case, I'm really curious and would love to know the answer.

推荐答案

如果你真的需要同步的休息的构造函数与任何线程,无论如何得到一个引用你尚未完全构造的对象,你可以使用同步块:

If you really need synchronization of the rest of the constructor versus any threads which anyhow gets a reference to your not-yet-totally-constructed object, you can use a synchronized-block:

public class Test {
    public Test() {
       final Test me = this;
       synchronized(this) {
          new Thread() {
             @Override
             public void run() {
                // ... Reference 'me,' the object being constructed
                synchronized(me) {
                   // do something dangerous with 'me'.
                }
             }
          }.start();
          // do something dangerous with this
       }
    }
}

通常被认为是不好的风格,给出你尚未构造的对象像这样,所以一个同步构造函数不是必需的。

Usually it is considered bad style to "give out" your not-yet-constructed object like this, so a synchronized constructor is not necessary.

在某些情况下,同步构造函数会很有用。这是一个更现实的例子,从讨论Bozho的答案:

In some corner cases a synchronized constructor would be useful. Here is a more realistic example, from the discussion of Bozho's answer:

public class SuperClass {

   public SuperClass() {
       new Thread("evil") { public void run() {
          doSomethingDangerous();
       }}).start();
       try {
          Thread.sleep(5000);
       }
       catch(InterruptedException ex) { /* ignore */ }
   }

   public abstract void doSomethingDangerous();

}

public class SubClass extends SuperClass {
    int number;
    public SubClass () {
        super();
        number = 2;
    }

    public synchronized void doSomethingDangerous() {
        if(number == 2) {
            System.out.println("everything OK");
        }
        else {
            System.out.println("we have a problem.");
        }
    }

}



只有在构造完我们的SubClass对象后才调用 doSomethingDangerous()方法,例如我们只想要一切OK输出。但在这种情况下,当你只能编辑你的SubClass,你没有机会实现这一点。如果构造函数可以同步,它会解决这个问题。

We want that the doSomethingDangerous() method is only called after construction of our SubClass object is complete, e.g. we only want the "everything OK" output. But in this case, when you only can edit your SubClass, you have no chance of achieving this. If the constructor could be synchronized, it would solve the problem.

所以,我们学到了什么:从来没有像我在超类构造函数中做的,如果你的类不是final - 并且不从您的构造函数调用自己的类的任何非final方法。

So, what we learn about this: never do something like I did here in the superclass constructor, if your class is not final - and don't call any non-final methods of your own class from your constructor.

这篇关于为什么Java构造函数不能同步?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆