1

プロパティでのロックの適切な使用について疑問に思っていました。スループットが非常に重要なマルチスレッドサーバーアプリケーションを作成しています。そのように宣言されたプロパティがある場合:

    private DataPoint a;
    private object aLock = new object();

最も保守的なロックは次のようです(方法1と呼びます)。ただし、この場合、最初の呼び出しの後のすべての呼び出しで、ロックのオーバーヘッドが発生します。

    public DataPoint A
    {
        get
        {
            lock (aLock)
            {
                if (a == null)
                {
                    a = new DataPoint();
                }

                return a;
            }
        }
    }

または、ロックを「a」を設定する行だけに移動する必要があります(方法2と呼びます)。この場合、「a」が数回設定される可能性がありますが(OK)、一度設定するとロックのオーバーヘッドはありません。

    public DataPoint A
    {
        get
        {
            if (a == null)
            {
                lock(aLock)
                {
                    a = new DataPoint();
                }
            }

            return a;
        }
    }

プロパティへの同時アクセスをロックするための推奨される方法は何ですか?それは方法1、方法2ですか、それとも上記のどれでもありませんか?

ありがとう。

4

3 に答える 3

7

.NET 4では、System.Lazy<T>次の問題を処理するタイプがあります。

class MyClass
{
    private readonly Lazy<DataPoint> lazy =
        new Lazy<Singleton>(() => new DataPoint());

    public DataPoint Instance { get { return lazy.Value; } }
} 

ジョンスキートの礼儀

于 2012-09-24T22:14:07.103 に答える
2

ロックの例では、値を初期化するためにロックしています。null条件が値を初期化する必要があることを意味すると仮定すると、ロックを取得する前後に値をチェックする必要があります。

if(a == null)
{
  lock(aLock)
  {
    if(a == null)
      a = new DataPoint();
  }
}

これは、スレッドがロックを待機しているときに、ロックを取得した後に実行する作業が、別のスレッドによってすでに実行されている可能性があるためです。したがって、スレッドがロックを取得すると、作業を実行する必要があるかどうかを確認する必要があります。

于 2012-09-24T22:06:57.333 に答える
1

ロックする前にnullをチェックする必要があります。nullの場合は、ロックして、nullをもう一度確認します。それでもnullの場合は、DataPointを開始し、最初に一時変数に割り当てます。完了したら、それをメンバーに割り当てて返却します。

private DataPoint _dataPoint;

public DataPoint A
{
    get
    {
        if(_dataPoint != null)
            return _dataPoint;

        lock (aLock)
        {
            if (_dataPoint == null)
            {
                var dataPoint = new DataPoint();
                // do more stuff with dataPoint
                _dataPoint = dataPoint;
            }

            return _dataPoint;
        }
    }
}
于 2012-09-24T22:07:38.943 に答える