1

我很好奇与 Java 方法同步和对象锁定有关的事情。

当您调用同步方法时,据我了解,它会在方法调用期间锁定整个对象。

这是否意味着您只需要同步将数据写入对象的方法,而不需要从对象中读取数据?

public class testclass {

    private ArrayList<String> data;

    public ArrayList<String> getData() {
        return data;
    }

    public synchronized void setData(ArrayList<String> data) {
        this.data = data;
    }
}

基本上上面的代码是线程安全的(因为 testclass 对象在运行 setData 方法时被锁定)?还是我也应该同步 getData 方法?

4

3 回答 3

3

这是否意味着您只需要同步将数据写入对象的方法,而不需要从对象中读取数据?

否 - 如果您不同步读取,则没有任何可见性保证(您可能会获得对象的陈旧版本)。

注意:在您的情况下,您不需要使用 synchronized 关键字,因为每个方法都是原子的 - 您可以简单地使用datavolatile 代替。

于 2012-09-17T09:23:57.833 回答
2

锁不是锁定对象本身,而是与对象关联的监视器。在您的情况下,即使方法 getData 的同步也不会使 testclass 线程安全,因为它会将“数据”字段的实例返回到狂野的世界,并且许多线程可能会以不可预知的顺序对对象做任何他们想做的事情。

为了遵循“可见性”,您要么需要使“数据”易失,要么同步这两种方法 - 因为 JVM 可以以任何方式自由优化字节码,这使得某些线程可以看到“陈旧”数据。

于 2012-09-17T09:26:01.757 回答
1

如果您没有方法,那么当一个线程首先调用并且另一个线程想要执行方法时,synchronize getData()您有什么保证,该线程没有被锁定。因此不是线程安全的。getData()writeData()

[编辑] 正如其他指定的那样,您返回非易失性数据对象也不是线程安全的,它可能会在此类之外以非线程安全的方式进行修改

于 2012-09-17T09:28:16.873 回答