我对与Java方法同步和对象锁定有关的事情感到好奇。
当您调用synchronized方法时,根据我的理解,它会在方法调用期间锁定整个对象。
这是否意味着您只需要同步将数据写入对象的方法,而不是从对象中读取数据?
public class testclass {
private ArrayList<String> data;
public ArrayList<String> getData() {
return data;
}
public synchronized void setData(ArrayList<String> data) {
this.data = data;
}
}
基本上上面的代码是线程安全的(因为在运行setData方法时,testclass对象被锁定)?或者我也应该同步getData方法?
答案 0 :(得分:3)
这是否意味着您只需要同步将数据写入对象的方法,而不是从对象中读取数据?
否 - 如果您不同步读取,则没有任何可见性保证(您可以获得该对象的陈旧版本)。
注意:在您的情况下,您不需要使用synchronized关键字,因为每个方法都是原子的 - 您可以简单地使data
变为volatile。
答案 1 :(得分:2)
锁不是锁定对象本身,而是与对象关联的监视器。在你的情况下,即使方法getData的同步也不会使testclass线程安全,因为它会将“data”字段的实例返回到wild world,并且许多线程可能以不可预测的顺序对对象做任何他们想做的事。
为了遵循“可见性”,您需要使“数据”易变,或者同步两种方法 - 因为JVM可以以任何方式自由优化字节码,这使得某些线程可以看到“陈旧”数据
答案 2 :(得分:1)
如果您没有synchronize
getData()
方法,当一个线程首先首先调用getData()
而另一个线程想要执行writeData()
方法时,您有什么保证?线程未锁定。因此不是线程安全的。
[编辑] 和其他指定的一样,返回非易失性Data对象也不是线程安全的,可以在此类之外以非线程安全的方式进行修改