我正在尝试对神秘停止的进程进行故障排除,并且我正在尝试确定我们是否会遇到变量被缓存并且不再读取的问题。
在我的场景中,我有一个发生在计时器上的操作(我将调用它Poll
)和一对外部函数,它们被调用以指示外部操作的开始和停止。由于细节不值得深入,这个假设的类不希望在外部操作发生时执行轮询操作。此外,外部操作可能同时发生多次,因此我使用计数器来指示正在进行的操作数。
当前的逻辑看起来或多或少像这个简化的例子:
class MyClass
{
private int operationsInProgress;
private void Poll() // Pretend we have a timer in place that's calling this periodically
{
var inProgress = operationsInProgress;
if (inProgress > 0) return;
DoSomething();
}
public void StartExternalOperation()
{
Interlocked.Increment(ref operationsInProgress);
}
public void EndExternalOperation()
{
Interlocked.Decrement(ref operationsInProgress);
}
}
假设:
- 两者
StartExternalOperation
和EndExternalOperation
都被调用了相同的次数——它们在 a 内被执行,try...finally
并且没有任何路径可以让孤儿Start
坐在外面 - 在不确定数量的执行之后的某个时刻,
DoSomething()
永远不会再次被调用。在我的真实场景中,我不知道确切原因,但我已经消除了除此之外我能找到的所有其他原因。
是否有可能是因为我没有在读取操作中使用任何类型的栅栏(通过Interlocked
或volatile
变量),值被缓存并且实际变量没有再次被读取?
由于这是一个我们无法可靠重现的问题,我需要知道我怀疑的原因是否合理。我可以更改代码以使用更正式的东西,例如ReaderWriterLock
(or Slim
),并且我知道我会有适当的逻辑,我只需要知道我所描述的是否可以合法地成为原因。