代码之家  ›  专栏  ›  技术社区  ›  Dan Bryant

这是正确的联锁同步设计吗?

  •  5
  • Dan Bryant  · 技术社区  · 16 年前

    我有一个取样系统。我在应用程序中有多个客户机线程对这些示例感兴趣,但实际的采样过程只能发生在一个上下文中。它足够快,可以在采样完成之前阻止调用过程,但是足够慢,我不希望多个线程堆积请求。我想出了这个设计(精简到最小的细节):

    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
        }
    }
    

    在我描述的场景中使用这个安全吗?

    2 回复  |  直到 16 年前
        1
  •  5
  •   Henk Holterman    16 年前

    是的,看起来很安全因为 int 这里是原子类型。但我还是会的

    private static int _isSampling;
    

    private static object _samplingLock = new object();
    

    使用方法:

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

    注意:我希望速度相当,lock使用内部使用Interlocked的managed Monitor类。

    我错过了退后方面,这里是另一个版本:

       if (System.Threading.Monitor.TryEnter(_samplingLock))
       {
         try
         {
             .... // sample stuff
         }
         finally
         {
              System.Threading.Monitor.Exit(_samplingLock);
         }
       }
    
        2
  •  -1
  •   Mike_G    16 年前

    我通常会声明一个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;
    }