有多個線程訪問單個對象。爲了避免內存一致性錯誤,我使用了該對象的同步方法。
這是否意味着當我在該對象上同步時,只有對象的字段被同步(而不是對象的字段的字段)? 例如:同步對象,然後在該對象的字段上
public class Class1 {
private Object value1;
public Object getValue1() {
return this.value1;
}
public void setValue1(Object value1) {
this.value1 = value1;
}
}
哪個代碼是正確的(Class2
或Class3
),爲什麼?
public class Class2 {
private final Class1 object1 = new Class1();
private Object value2;
public synchronized void setValues(Object value1, Object value2) {
object1.setValue1(value1);
this.value2 = value2;
}
public synchronized Object[] getValues() {
return new Object[] { object1.getValue1(), this.value2};
}
}
public class Class3 {
private final Class1 object1 = new Class1();
private Object value2;
public synchronized void setValues(Object value1, Object value2) {
synchronized (object1) {
object1.setValue1(value1);
}
this.value2 = value2;
}
public synchronized Object[] getValues() {
Object value1;
synchronized (object1) {
value1 = object1.getValue1();
}
return new Object[] { value1, this.value2};
}
}
更具體的:
Class2 obj = new Class2();
// thread 1
obj.setValues(..., ...);
// thread 2
Object[] values = obj.getValues();
由於兩個setValues
和getValues
同步會有在Class2
this.value2 = value2;
和return new Object[] {..., this.value2};
之間之前發生的關係。
但是object1
呢?沒有保證this.value1 = value1;
發生在return this.value1;
在Class1
之前。不是嗎?
因此,在Class2中訪問'object1'的'value1'時不會出現內存一致性錯誤?爲什麼? 'object1'和'value2'都是參考字段,只有那些字段的值(即對象在存儲器中的地址)被同步。 'value2'很好,因爲我們不訪問它自己的狀態。但是'object1'的'value1'呢?是否有可能獲得「舊」價值而不是新價值?爲什麼? – Victor 2015-04-03 08:41:18
@Victor:你不同步字段;你同步*線程*。再次說明:您的示例具有一個** private **'Class'實例,並且該實例的唯一訪問權限是通過同步包含它的實例的同步方法。因此,在任何給定的時間只有一個線程可以使用這些方法,並且不必進行進一步的同步。但那只是因爲你的類有一個沒有其他人訪問的私有實例。不要想到同步字段,請考慮使用這些字段的*線程*。 – 2015-04-03 09:00:10