2012-04-12 72 views
9

是否有任何理由在此代碼中一起使用volatile和同步?同步在一起的易失性

public class Helper { 
    private volatile int n; 
    private final Object lock = new Object(); 
    public Helper(int n) { 
    this.n = n; 
    } 

    public void setN(int value) { 
    synchronized (lock) { 
     n = value; 
    } 
    } 
} 

類助手必須是線程安全的。我已經從「Java併發準則」一書中得到了這個例子,但是它仍然不清楚:在這個例子中使用volatile和synchronized的原因是什麼?

+1

你說的確切的書是什麼?我強烈建議Java併發實踐書(http://jcip.net/)學習Java併發性。 – 2012-04-12 11:50:00

+0

心中已經發現了這本書在這裏(第167頁) http://www.sei.cmu.edu/reports/10tr015.pdf 一切都在這本書中,除了這種情況下,僅使用 – 2012-04-12 11:50:56

+0

相當的AtomicInteger清楚。 – khachik 2012-04-12 12:02:56

回答

7

這個例子的目的是指出syncronized沒有volatile是不夠的,在這種情況下,鑑於對象可不安全公佈(即不volatileFoo):

如果幫手Foo類中的字段未聲明爲volatile,因此應將n字段聲明爲volatile,以便在初始化n和將Helper寫入幫助程序字段之間建立before-before關係。這符合準則「VNA06-J」。不要認爲聲明一個對象引用volatile保證其成員的可見性「(第35頁)。只有當調用者(類Foo)不能被信任來聲明助手volatile時,才需要這樣做。

這是正確的,但他們選擇了一個糟糕的例子來說明,因爲沒有volatile是syncrhonization足夠在這種情況下。

0

我猜測,揮發性的使用,因爲「否」的構造

+0

是的,但是在setN方法中使用同步的原因是什麼? – 2012-04-12 11:53:47

+0

真的嗎?我不知道如何從2個或更多線程調用同一對象的構造函數,是嗎? – hsestupin 2012-04-12 11:59:51

+0

我不知道)我的問題是關於爲什麼setN方法需要同步。如果n變量是易失性的,setter可以沒有任何額外的同步。或不? – 2012-04-12 12:12:45

1

這是沒有必要把synchronized塊圍繞價值的變動被設置;自Java 5以來,這對於volatile變量「自動」完成。我認爲在Java 5之前,情況並非一定如此。