2017-03-07 2 views
2

アプリケーションのマルチスレッドに関連すると思われるバグを追跡しようとしています。私は以下のコードを簡略化しました:外部関数からのロックと参照の値

class Outer { 
    private static int count; 

    //this function is called from multiple threads in quick succession 
    public void DoFoo() { 
    Inner.Increment(ref count); 
    } 
} 

class Inner { 
    private readonly static object mLock = new object(); 
    public static string Increment(ref count) { 
    lock (mLock) (
     if (count > 1000) 
     count = 0; 
     count++; 
    } 
    return count.ToString(); 
    } 
} 

変数の安全性を保証する方法はありますか?カウントが何かコピーされているかどうかはわかりませんが、メモリの安全性が損なわれる可能性がありますか?私はそれが新しいintを返すかもしれないと思っていたし、メソッドの終わりに、または何かを割り当てます。それとは別に、ロックセクションはキャッシュの問題を処理すると私は理解しています。

私たちの注意を引いて問題を買ったエラーは、見かけ上、カウントが古くなっているスレッドの1つでした。

答えて

2

ここでの問題は、あなたが最初のロックを取得せずにOuter.countにアクセスすることができますので、それが(通常はあなたのコードで書かれたとして、countは0のみ最初の前にすることができ、== 0のとき、いくつかの他のスレッドが直接Outer.countを読むことができるということです唯一の1と1001年)の間の値を持つことができ、それに続いから、Inner.Incrementに呼び出す

ロックなしでは、この方法で行うことができます

Interlocked.CompareExchangeを通じて(

class Inner 
{ 
    public static string Increment(ref int count) 
    { 
     while (true) 
     { 
      int original = count; 
      int next = original; 

      if (next > 1000) 
      { 
       next = 0; 
      } 

      next++; 

      if (Interlocked.CompareExchange(ref count, next, original) == original) 
      { 
       return next.ToString(); 
      } 
     } 
    } 
} 

私はnext値を計算し、それを使用しています) 私だけその間にf countは変更されていません。

+0

これは私が考えていたものですが、ロックステートメントが入力されたとき(参照のため)最新の値を取得するのでしょうか、それとも無効な値に固執しますか? – flukus

+0

@flukus私の変更されたコードを見てください。 – xanatos

+0

これは、外部から渡された古い値の問題を解決するでしょうか? – flukus

関連する問題