我有一个带样品的系统。我在应用程序中有多个对这些示例感兴趣的客户端线程,但是获取Sample的实际过程只能在一个上下文中进行。它足够快,它可以阻止调用过程,直到完成采样,但足够慢,我不希望多个线程堆积请求。我想出了这个设计(剥离到最小的细节):
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
}
}
在我描述的场景中使用它是否安全?
答案 0 :(得分: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);
}
}
答案 1 :(得分:-1)
我通常会声明一个不稳定的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;
}