无锁参考计数

Jef*_*eff 6 .net c# concurrency locking reference-counting

我正在研究一个需要广泛的C API互操作的系统.部分互操作需要在任何操作之前和之后初始化和关闭相关系统.如果不这样做将导致系统不稳定.我通过简单地在核心一次性环境类中实现引用计数来实现这一点,如下所示:

public FooEnvironment()
{
  lock(EnvironmentLock)
  {
    if(_initCount == 0)
    {
      Init();  // global startup
    }
    _initCount++;
  }
}

private void Dispose(bool disposing)
{
  if(_disposed)
    return;

  if(disposing)
  {
    lock(EnvironmentLock)
    {
      _initCount--;
      if(_initCount == 0)
      {
        Term(); // global termination
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

这很好,并完成了目标.但是,由于任何互操作操作必须使用块嵌套在FooEnvironment中,因此我们始终锁定并且分析表明此锁定占运行时期间完成工作的近50%.在我看来,这是一个基本的概念,.NET或CLR中的某些东西必须解决它.有没有更好的方法来进行引用计数?

Gre*_*g D 6

这是一个比你初看起来更狡猾的任务.我不相信Interlocked.Increment足以完成你的任务.相反,我希望你需要使用CAS(比较和交换)执行一些魔法.

还要注意,这很容易实现这一点,但是当程序与heisenbugs崩溃时,大多数情况下仍然是完全错误的.

在走这条道路之前,我强烈建议进行一些真正的研究.如果你搜索"锁定免费引用计数",一对好的跳跃点会弹到顶部. 这篇Dobbs博士的文章很有用,这个SO问题可能是相关的.

最重要的是,请记住,无锁编程很难.如果这不是您的专业,请考虑退回并根据参考计数的粒度调整您的期望.如果您不是专家,重新考虑您的基本引用计数政策可能要比创建可靠的无锁机制要便宜得多.特别是当你还不知道无锁技术实际上会更快.