1

2 つのプロパティと 2 つのメソッドを持つクラスがあります。たとえば下のようなものです。(データ型または戻り値の型は無視してください。これは典型的なシナリオです)

// The methods could be invoked by multiple threads
    public class Stock
    { 

    private static int FaceValue {get; set;}
    private static int Percent (get; set;}

    //    method that updates the two properties
    Public void UpdateStock()
    {
      FaceValue += 1;
      Percent = FaceValue * 100;
    }

    //   method that reads the two properties
    public int[] GetStockQuote()
    {
        return new int[] { FaceValue, Percent};
    }

    }

このクラスがスレッドセーフであることを確認する必要があります。両方のメソッドで lock(obj) をスレッドセーフにするための 1 つの手法として使用できますが、次の点を考慮すると、スレッドセーフにするための最良の手法は何でしょうか。

  1. 読み取り/更新されるプロパティは 2 つだけです。したがって、メソッド内でロックすることが適切な手法であるかどうかはわかりません。

  2. メソッドやクラスではなく、プロパティをスレッドセーフにするだけで十分でしょうか?

  3. また、個々のメソッドやプロパティではなく、クラス全体をスレッドセーフにする方法はありますか? .Net 4.0 から推奨されるロック手法はありますか?

私がこの権利を考えているのか、それともこれらを考慮して複雑にしすぎているのか疑問に思っています. これを明確にするために、事前に感謝します。

マニ

4

2 に答える 2

6

一般に、ここでは alockがおそらく最も単純なアプローチです。

潜在的により良い代替手段は、このクラスをimmutableにすることです。一度作成したクラス内の値を変更できないようにすると、値を変更する方法がないため、値を読み取るときに心配する必要がなくなります。

この場合、2 つの値を取るコンストラクターを用意し、次のUpdateStockように変更することで実現できます。

public Stock GetUpdatedStock()
{
     // Create a new instance here...
     return new Stock(this.FaceValue + DateTime.Now.MilliSecond, this.FaceValue * 100);
}

編集:

FaceValue と Percent をstaticにしたので、同期が必要になります。ここではおそらくAlockが最も単純なオプションです。

単一の値の場合、 Interlocked クラスを使用して更新をアトミックに処理できる可能性がありますが、両方の値のアトミック更新を行う方法はありません*。これは、スレッド セーフを適切に行うために必要になる可能性があります。この場合、を介して同期するlockと問題が解決します。

*注意: これは、クラス内に両方の値を置き、クラス インスタンス全体を交換する場合、ロック ビアなしで実行できる可能性があります。Interlocked.CompareExchange

于 2012-10-08T15:51:52.463 に答える
1

スレッドセーフにするための特効薬の解決策はありません。シナリオごとに独自の解決策が必要です。最も明白なのは を使用することlockですが、あなたの例では、Interlockedクラスを単純化して使用し、これをアトミック操作にすることができます。

public class Stock
{ 

    private static int FaceValue {get; set;}

    Public void UpdateStock()
    {
       //only a single property to update now
       Interlocked.Increment(FaceValue);
    }

    //   method that reads the two properties
    public int[] GetStockQuote()
    {
        var currVal = FaceValue;
        return new int[] { currVal, currVal * 100 };
    }

}

MSDN のインターロックを参照してください。

于 2012-10-08T16:17:14.653 に答える