2015-12-30 64 views
3

有些東西我還不瞭解同步和易失性。易失性和同步

我知道一個線程可以在本地進行安全更改。從我迄今爲止讀過的是同步的>易失性的。

說我有一個參數不長或基本上是一個標準的整數(無原子)。

而我有一個同步的方法,我用這個Integer做了很多工作。 所有線程是否會獲得此Integer的更新版本?或者我還必須聲明它是不穩定的?

public class stackoverflow { 

    private int x = 0; 

    public synchronized void rechnen(){ 
     //dosomething 
    } 
} 

後基本上rechnen()之後,我得到了10000成一線,都將得到x的更新版本,因爲我的方法是同步的?還是我必須聲明它是不穩定的?

+0

請用您正在使用的編程語言標記您的問題。 –

回答

5

是的,他們會得到更新版本。​​保證兩件事情:變化和原子性的可見性。 volatile只是保證變更的可見性。 Java保證同步塊內部的代碼不會被優化(通過混合​​塊內外的命令),因此每個更改內部變量的內容都將在同步塊結束後對所有線程可見。

+1

「當然,對於所有線程來說,每次更改內部變量都是可見的」,但我認爲這是不正確的,「Java保證同步塊內的代碼不會被優化」。 –

+0

@ v.ladynev是的,你是對的。我沒有寫得那麼好。我編輯了答案。我在想的是Java不會通過在'synchronized'塊內部和外部混合語句來優化代碼。 – partlov

+1

_...每次更改內部變量,在同步塊結束後,所有線程都將可見._不完全正確。 JLS只保證,如果線程A更新一個變量然後退出一個同步塊,那麼線程B將能夠看到更新_線程B在同一個對象上同步後。_ –

1

同步方法已經存在於您的代碼中。此外,你需要設置你的X揮發性如下

private volatile int x = 0; 

這將確保訪問這個動盪領域的線程,將首先從主內存中讀取,而不是使用緩存值

潛在CPU的電流值,

這樣可以保證你的代碼是線程安全的

+0

這個答案可能是錯誤的 - 我們不知道這段代碼中的關鍵部分是什麼,所以在這種情況下,volatile可能不夠。問題中沒有足夠的細節。 –

+0

@RobinGreen我告訴volatile判斷數據不是來自緩存,他也需要使用synchronized方法。 – Thanga

+0

@Thanga,如果同一個變量'x'的所有用法在同一個對象上同步,那麼就不需要'x'變爲'volatile'變量。 Java語言規範意味着,在一個線程離開一個同步塊之前,變量中存儲的任何變量在進入任何在同一個對象上同步的塊之後,對其他線程都是可見的。 –

3

是的,他們將獲得更新的版本,但只有當他們進入一個synchronized塊自己。如果他們沒有在同一個對象上輸入同步塊(鎖定同一個監視器),則不能保證他們會看到更新。

如果你不想讓其他線程進入同步塊,那麼你必須聲明變量爲volatile。

+2

它不一定是同一個同步塊。它_does_必須是在同一個鎖對象上同步的塊。 –

-1

聲明private volatile int x = 0;它會滿足你的目的。爲了更好的理解,請參閱AtomicInteger的實現。

2

@partlov已經回答了您的問題,所以您可能需要考慮其他一些事項。

聲明的方法時爲synchronized它使用一個顯示器不要使用同步作爲改性劑

。在Java中,每個Object恰好是一個監視器,在這種情況下使用類實例。所以你的例子情意上變成:

public void rechnen(){ 
    synchronized(this) { 
     //dosomething 
    } 
} 

現在,這可能會造成潛在的問題,因爲你正在泄漏你的顯示器。應用程序的其他部分可以使用此相同的監視器來同步完全不相關的代碼,這可能導致/導致性能下降,或者更糟糕的是,它可能會導致意外的死鎖。

因此,主要建議是始終保持顯示器的私密性。因此,像:

public class stackoverflow { 
    private final Object monitor = new Object(); 
    private int x = 0; 

    public void rechnen(){ 
     synchronized(monitor) { 
      //dosomething 
     } 
    } 
} 

知道你的API

之間volatile和​​存在的具體併發目的的工具太多了。其中大部分使用volatile,​​和CAS-operations的混合。例如AtomicInteger爲您提供了原子整數運算,其競爭非常少,正如​​通常所見。所以請儘量熟悉java.util.concurrent