2011-11-15 65 views
1

我在應用程序中得到了「對易失性字段的引用不會被視爲易失性」的警告。我明白爲什麼。使用volatile關鍵字和鎖定語句

作爲一個簡單的例子,下面的代碼將使問題線程安全,即使我仍然會得到警告?

private volatile int myVal = 10; 
private int myNonVolatileNumber = 50; 
private static readonly object lockObject = new object(); 

private void ChangeValue(ref int Value) 
{ 
    lock (lockObject) 
    { 
    Value = 0; 
    } 
} 

private void MyMethod() 
{ 
    ChangeValue(ref myVal); //Warning here 
    ChangeValue(ref myNonVolatileNumber); //no warning 
} 
+2

請注意'Interlocked'類。 – SLaks

+0

遞增是一個錯誤的例子。請參閱更新後的問題 – Jon

+0

這將串行化所有對'ChangeValue'的調用,我懷疑是您想要的。 – Jodrell

回答

2

鎖定強制雙方的內存障礙,所以是的,你的例子是線程安全的。

+0

我想我會堅持一個鎖! – Jon

1

你幾乎自己回答吧:

ChangeValue(ref myVal); //Warning here 
ChangeValue(ref myNonVolatileNumber); //no warning 

只有1編譯ChangeValue(),裏面的代碼應該實現 '揮發' 行爲的副本。但編譯器(Jitter)在編譯時無法預測所有調用。唯一的選擇是將 ref參數作爲易失性來對待,這將是非常低效的。

但請參閱@史蒂文的評論,volatile是一樣好,無用,應該避免。

0

什麼是錯

private int val = 10; 
private var valLock = new object(); 
private int nonVolatileNumber = 50; 
private var nonVolatileNumberLock = new object(); 

public int Value 
{ 
    get { lock(valLock) return val; } 
    set { lock(valLock) val = value; } 
} 

public int NonVolatileNumber 
{ 
    get { lock(nonVolatileNumberLock) return nonVolatileNumber; } 
    set { lock(nonVolatileNumberLock) nonVolatileNumber = value; } 
} 

,這裏唯一的風險是後續代碼訪問該屬性的私有成員。

在32位整數或64位系統上,甚至64位整數的情況下,becasue的讀取西港島線是原子,你可以使用Interlocked類這樣的...

private int val = 10; 

public int Value 
{ 
    get { return val; } 
    set { Interlocked.Exchange(ref val, value); } 
} 

還是在的情況下,更復雜的類型,你可以使用ReadWriterLockSlim ...

private SomeStructure complex; 
private var complexLock = new ReadWriterLockSlim(); 

public SomeStructure Complex 
{ 
    get 
    { 
     complexLock.EnterReadLock(); 
     try 
     { 
      return complex; 
     } 
     finally 
     { 
      complexLock.ExitReadlock(); 
     } 
    } 
    set 
    { 
     complexLock.EnterWriteLock(); 
     try 
     { 
      return complex; 
     } 
     finally 
     { 
      complexLock.ExitWritelock(); 
     } 
    } 
} 

這是一個比一個標準的鎖更好,因爲它允許多個併發的讀寫。