5

サンプルを取るシステムがあります。これらのサンプルに関心のあるアプリケーションに複数のクライアント スレッドがありますが、サンプルを取得する実際のプロセスは 1 つのコンテキストでしか発生しません。サンプリングが完了するまで呼び出しプロセスをブロックしても問題ないほど高速ですが、複数のスレッドが要求を積み上げたくないほど遅いです。私はこのデザインを思いつきました(最小限の詳細に落とし込みました):

public class Sample
{
    private static Sample _lastSample;
    private static int _isSampling;

    public static Sample TakeSample(AutomationManager automation)
    {
        //Only start sampling if not already sampling in some other context
        if (Interlocked.CompareExchange(ref _isSampling, 0, 1) == 0)
        {
            try
            {
                Sample sample = new Sample();
                sample.PerformSampling(automation);
                _lastSample = sample;
            }
            finally
            {
                //We're done sampling
                _isSampling = 0;
            }
        }

        return _lastSample;
    }

    private void PerformSampling(AutomationManager automation)
    {
        //Lots of stuff going on that shouldn't be run in more than one context at the same time
    }
}

これは、私が説明したシナリオで安全に使用できますか?

4

2 に答える 2

5

intはい、ここではアトミック型なので安全に見えます。しかし、私はまだ交換することをお勧めします

private static int _isSampling;

private static object _samplingLock = new object();

そして使用:

lock(_samplingLock)
{
    Sample sample = new Sample();
    sample.PerformSampling(automation);
   _lastSample = sample;
}

これは単に推奨されるパターンであり、_lastSample へのすべてのアクセスが正しく処理されるようにするためです。

注意: 同等の速度が期待できます。lock は、Interlocked を内部的に使用する管理された Monitor クラスを使用します。

編集:

バックオフの側面を見逃しました。別のバージョンを次に示します。

   if (System.Threading.Monitor.TryEnter(_samplingLock))
   {
     try
     {
         .... // sample stuff
     }
     finally
     {
          System.Threading.Monitor.Exit(_samplingLock);
     }
   }
于 2010-04-07T21:27:30.080 に答える
-1

私は通常、volatile bool を宣言し、次のようなことを行います。

private volatile bool _isBusy;
private static Sample _lastSample;

private Sample DoSomething()
{
     lock(_lastSample)
     {
       if(_isBusy)
          return _lastSample;
       _isBusy = true;
     }

     try
     {
       _lastSample = new sameple//do something
     }
     finally
     {
        lock(_lastSample)
        {
           _isBusy = false;
        }
     }
     return _lastSample;
} 
于 2010-04-07T21:37:44.663 に答える