2011-11-15 11 views
1

アプリケーションで、「volatileフィールドへの参照がvolatileとして扱われない」という警告が表示されています。私は理由を理解する。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 

コンパイルChangeValue(の1つだけコピーがあります)、内部コードは「揮発性の行動を実装する必要があります。コンパイラ(Jitter)はコンパイル時にすべての呼び出しを予測できません。唯一のオプションは、のrefパラメータをvolatileとして扱うことです。これは非常に非効率的です。

しかし、@ Stevenのコメントvolatileは役に立たないほど良く、避けるべきです。

1

おそらく、使用した場所でvolatileキーワードを使用する必要はありません。

これはSOですべての場合、すべての揮発性のキーワードを使用しなければならない必要がある答えを質問:When should the volatile keyword be used in C#?

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ビットの整数の場合

、WILがアトミックで読み取っbecasue、あなたが

private int val = 10; 

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

かの場合には...このようInterlockedクラスを使用することができますあなたはそれが複数の同時読み取りができますので、これは、標準的なロックよりも優れている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(); 
     } 
    } 
} 

を使用することができ、より複雑なタイプ。

関連する問題