考虑一个代表一个简单单元格的类:
class Cell {
private int x;
Cell(int x) {
this.x = x;
}
int getX() {
return x;
}
void setX(int x) {
this.x = x;
}
}
如果我想让它成为线程安全的,我应该只使方法同步还是构造函数呢?
class Cell {
private int x;
Cell(int x) {
synchronized(this) { // <- Is this synchronization necessary?
this.x = x;
}
}
synchronized int getX() {
return x;
}
synchronized void setX(int x) {
this.x = x;
}
}
如果是,为什么synchronized
构造函数中没有java.util.Vector
块?
答案 0 :(得分:4)
没有实际需要同步构造函数, 因为它会锁定正在构建的对象,这通常是 直到所有构造函数都没有提供给其他线程 对象已经完成了他们的工作。
这意味着引用在被访问之前被同步。
由于您正在正确同步,因此可以说构造函数中发生的写入会在对象发布之前发生,只要同步在所述字段上是一致的
在您的情况下,由于getX()
和setX()
都已同步,因此同步是一致的,您无需在构造函数中进行同步。
现在,你需要在构造函数上synchronize(this)
吗? 否,正如JLS所提到的那样,在你不知道的情况下隐式同步。
答案 1 :(得分:1)
这提出了一个重要的切向点 - 你永远不应该允许对象的引用从其构造函数中逃脱,因为这将允许访问部分构造的对象。
因此,假设您遵循此编程规则,您永远不需要同步构造函数,因为在构造函数返回之前,没有方法,并发或其他方法可以访问对象。因此,同步没有逻辑意义。
答案 2 :(得分:0)
不,您不需要同步构造函数,因为只要您在构造函数中,引用就不会泄露给另一个线程。
除此之外:
答案 3 :(得分:-1)
您的情况不需要。
在您的情况下,您正在访问实例变量,该变量仅在一个线程中可访问/可见,因为您在构造函数中。您将调用构造函数,您正在分配内存和方法结束调用,返回调用方法的唯一指针,因此指针/实例对于Thread是唯一的。
收到指针后。如果指针/对象变量在多个线程中共享,就像这样。
Object obj = new Object();
Thread t1 = new Thread(new x(obj));
Thread t2 = new Thread(new x(obj));
Class x implements runnable{
Object obj;
x (Object obj){
this.obj = obj;
}
run() {
// do some operation on Obj -
}
}
}
在这种情况下,obj在多个线程之间共享,因此您的实例变量x
会受到竞争条件的影响。所以你必须确保用其他方法包装。
这就是为什么向量构造函数没有sycn块但其他方法没有。
假设您在此类中有一个静态变量。然后需要通过同步块进行换行,因为任何一个都可以访问它。
答案 4 :(得分:-2)
构造函数永远不应该同步,因为我猜它不实用。(你什么时候需要同时从不同的地方调用相同的构造函数?)