2009-01-08 56 views
38

下面的代碼「的揮發性字段的引用將不會被視爲波動」的影響

using System.Threading; 

class Test 
{ 
    volatile int counter = 0; 
    public void Increment() 
    { 
     Interlocked.Increment(ref counter); 
    } 
} 

引發以下編譯器警告:

"A reference to a volatile field will not be treated as volatile" 

我做錯了什麼在這裏提出這個警告?爲什麼編譯器我會對此提出警告?

回答

39

你沒有做錯任何事情。根據documentation

揮發性字段通常不應 使用ref或out 參數傳遞,因爲它不會被 功能的範圍內 視爲揮發性。對此,有例外 ,例如調用 互鎖API時。

3

由於您通過引用傳遞字段,所以出現錯誤。我認爲這意味着目標方法不知道該字段標記爲volatile,因此不會將其視爲這樣。

30

基本上警告的是,當您通過引用傳遞一個易失性字段時,調用代碼不知道以易失性方式處理它。對於Interlocked.Increment而言,由於方法的性質可能無關緊要,但如果您使用的是Interlocked,那麼您無需將變量揮發起來

在一般情況下,我想我會避免將兩者混合 - 如果你正在使用互鎖,做到處(使用Interlocked.CompareExchange(ref counter, 0, 0)讀它)。我不能說我經常親自使用揮發性物質。對於簡單的計數器,我可能使用使用聯鎖,但我更可能在大多數任務中使用鎖。

+0

你讓我感到困惑。在之前的問題(395232)中,我從你的回答中瞭解到,我需要互鎖和易變。現在你說「如果你使用Interlocked,你不需要這個變量變得不穩定。」 – 2009-01-08 17:33:03

+0

不,他們是互相替代的:「或者最好使用互鎖,一個易變的變量或鎖。」這是爲了給三個*不同的方法,而不是一個組合。那是誤導你的部分嗎? – 2009-01-08 17:52:29

+0

我知道在多處理器環境中,多個緩存可以使一個處理器遞增一個不是最後一個值的緩存值。在這種情況下,據我所知,Interlocked不會有幫助,因爲它不會創建刷新高速緩存所需的MemoryBarrier。 – 2009-01-09 02:25:14

26

使用此:

 #pragma warning disable 420 
     //      M 
     //      dM 
     //      MMr 
     //      4MMML     . 
     //      MMMMM.    xf 
     //  .    "MMMMM    .MM- 
     //  Mh..   +MMMMMM   .MMMM 
     //  .MMM.   .MMMMML.   MMMMMh 
     //  )MMMh.  MMMMMM   MMMMMMM 
     //  3MMMMx.  'MMMMMMf  xnMMMMMM" 
     //  '*MMMMM  MMMMMM.  nMMMMMMP" 
     //   *MMMMMx "MMMMM\ .MMMMMMM= 
     //   *MMMMMh "MMMMM" JMMMMMMP 
     //    MMMMMM 3MMMM. dMMMMMM   . 
     //    MMMMMM "MMMM .MMMMM(  .nnMP" 
     // =..   *MMMMx MMM" dMMMM" .nnMMMMM* 
     // "MMn...  'MMMMr 'MM MMM" .nMMMMMMM*" 
     //  "4MMMMnn.. *MMM MM MMP" .dMMMMMMM"" 
     //  ^MMMMMMMMx. *ML "M .M* .MMMMMM**" 
     //   *PMMMMMMhn. *x > M .MMMM**"" 
     //    ""**MMMMhx/.h/ .=*" 
     //      .3P"%.... 
     //     nP"  "*MMnx 
     if(Interlocked.CompareExchange(ref isLoaded, 1, 0) != 0) 
      return; 
     #pragma warning restore 420 
相關問題