2016-08-03 76 views
1

A的方法由兩個線程訪問。一個線程更新它。另一個檢索其成員。通過訪問器檢索實例成員的線程安全

public class A { 
    private V v; 

    public V getV() { 
     return v; 
    } 

    public V updateV(A a, B b, Cc) { 
     //complex logic updating V 
    } 
} 

我該如何讓V線程安全?

+0

請提供V –

+1

的代碼是否正在更新** V的現有實例還是正在創建一個替換舊實例的新實例? – Fildor

+1

您能否從getter返回'v'的防禦副本,還是必須在所有以前返回的實例中都可見? –

回答

2

使V線程安全的最簡單的方法是讓不變(通過使最終所有的非靜態字段),然後在A只需在updateV作爲未來影響V一個新實例:

public class A { 
    private V v; 

    public synchronized V getV() { 
     return v; 
    } 

    public synchronized V updateV(A a, B b, Cc) { 
     //complex logic updating V 
     this.v = new V(...); 
     return v; 
    } 
} 

正如你可以看到使A線程安全的,我只是添加關鍵字​​吸氣劑,防止併發讀寫,但如果你的情況是不是需要它,你可以門坎使v volatile在明年的二傳:

public class A { 
    private volatile V v; 

    public V getV() { 
     return v; 
    } 

    public V updateV(A a, B b, Cc) { 
     //complex logic updating V 
     this.v = new V(...); 
     return v; 
    } 
} 
+0

如果您只使用同步版本,則不會保證該字段不再位於緩存中。在這種情況下,您應該使用volatile來確保可見性。 –

+0

@NicolasHenneaux我不這麼認爲,你使用同步或不穩定不檢查,例如類Vector的代碼(或基於同步的任何線程安全類),你會看到代表狀態的所有字段都不易揮發 –

+1

Your在同一對象(本例中爲實例)上使用同步關鍵字會導致內存障礙(請參閱https://stackoverflow.com/questions/3519664/difference-between-volatile-and-synchronized-in-java)。 –