【发布时间】:2012-09-18 15:32:54
【问题描述】:
有人告诉我Java构造函数是同步的,因此在构造过程中不能同时访问它,我想知道:如果我有一个将对象存储在映射中的构造函数,并且另一个线程从该映射中检索它在它的构造完成之前,该线程会阻塞直到构造函数完成吗?
让我用一些代码来演示一下:
public class Test {
private static final Map<Integer, Test> testsById =
Collections.synchronizedMap(new HashMap<>());
private static final AtomicInteger atomicIdGenerator = new AtomicInteger();
private final int id;
public Test() {
this.id = atomicIdGenerator.getAndIncrement();
testsById.put(this.id, this);
// Some lengthy operation to fully initialize this object
}
public static Test getTestById(int id) {
return testsById.get(id);
}
}
假设 put/get 是地图上唯一的操作,所以我不会通过迭代之类的方式获得 CME,并尝试忽略此处的其他明显缺陷。
我想知道的是,如果另一个线程(显然不是构造对象的线程)尝试使用getTestById 访问对象并在其上调用某些东西,它会阻塞吗?换句话说:
Test test = getTestById(someId);
test.doSomething(); // Does this line block until the constructor is done?
我只是想澄清一下构造函数同步在 Java 中的进展情况,以及这样的代码是否会出现问题。我最近看到了这样的代码,而不是使用静态工厂方法,我想知道这在多线程系统中有多危险(或安全)。
【问题讨论】:
-
你在考虑静态初始化吗?一般来说,可变静态和特别是自注册构造函数几乎总是一个坏主意。
-
@TomHawtin-tackline 我知道正确同步的静态工厂方法是首选方法,我只是想知道这段代码是否存在任何功能问题,或者代码是否真的会中断。
-
我已取消删除我匆忙(以前是错误的)答案@Brian FYI。重要的一点是,当您在 any 对象(或者如果您引用
volatile字段)上调用synchronized时,all 内存在线程之间同步。不仅仅是你synchronized上的对象。
标签: java multithreading concurrency constructor