我应该同步构造函数吗?

时间:2014-04-11 15:24:58

标签: java concurrency synchronized

考虑一个代表一个简单单元格的类:

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块?

5 个答案:

答案 0 :(得分:4)

根据JLS#8.8.3

  

没有实际需要同步构造函数,   因为它会锁定正在构建的对象,这通常是   直到所有构造函数都没有提供给其他线程   对象已经完成了他们的工作。

这意味着引用在被访问之前被同步。

由于您正在正确同步,因此可以说构造函数中发生的写入会在对象发布之前发生,只要同步在所述字段上是一致的

在您的情况下,由于getX()setX()都已同步,因此同步是一致的,您无需在构造函数中进行同步。


现在,你需要在构造函数上synchronize(this)吗? ,正如JLS所提到的那样,在你不知道的情况下隐式同步。

答案 1 :(得分:1)

这提出了一个重要的切向点 - 你永远不应该允许对象的引用从其构造函数中逃脱,因为这将允许访问部分构造的对象。

因此,假设您遵循此编程规则,您永远不需要同步构造函数,因为在构造函数返回之前,没有方法,并发或其他方法可以访问对象。因此,同步没有逻辑意义。

答案 2 :(得分:0)

不,您不需要同步构造函数,因为只要您在构造函数中,引用就不会泄露给另一个线程。

除此之外:

  1. 考虑让你的类不可变。然后不需要同步。
  2. 我宁愿不像这个同步一样创建一个简单的类,而是将同步保留给类的用户。如果只从一个线程访问同一个对象,则不需要同步。

答案 3 :(得分:-1)

您的情况不需要。

  1. 如果要访问可共享数据,则需要通过sych块进行换行。
  2. 在您的情况下,您正在访问实例变量,该变量仅在一个线程中可访问/可见,因为您在构造函数中。您将调用构造函数,您正在分配内存和方法结束调用,返回调用方法的唯一指针,因此指针/实例对于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)

构造函数永远不应该同步,因为我猜它不实用。(你什么时候需要同时从不同的地方调用相同的构造函数?)

Here is the further information: