【问题标题】:Log when a thread is waiting on arrival at a lock statement记录线程在到达锁定语句时等待的时间
【发布时间】:2011-10-12 15:27:13
【问题描述】:

当一个线程到达一个线程时,有没有一种快速的方法来记录一个线程正在等待一个锁

lock(x)
{
  //do work on a collection

}

?

如果线程 1 到达锁,并且块中没有另一个线程,则应该没有日志。那么如果线程 2 到达 lock(x) 并且线程 1 仍然在块中,那么应该有一个日志。理想的解决方案不需要切换到 Mutex 或 Monitor 会增加太多复杂性。如果有一种使用 TPL、PLINQ 或 RX 的快速简便的方法来做到这一点,那就太好了。

【问题讨论】:

  • 我认为您必须将 lock 的简写扩展为等效的长写并手动插入日志记录。
  • 当我说理想的解决方案不需要切换到互斥锁时,我的意思是它不需要明确使用互斥锁或监视器。我编辑了最初的问题以反映这一点。我确实需要这个只是为了调试并且希望语法尽可能简单。
  • 那么 PostSharp 就是要走的路。

标签: c# locking system.reactive task-parallel-library plinq


【解决方案1】:

您可以de-sugar the lock statement 并使用Monitor.TryEnter 来检查是否可以在不等待的情况下获取锁:

bool lockTaken = false;
var obj = x;
try
{
    Monitor.TryEnter(obj, ref lockTaken);
    if (!lockTaken)
    {
        Log();
        Monitor.Enter(obj, ref lockTaken);
    }
    //do work on a collection
}
finally
{
    if (lockTaken)
    {
        Monitor.Exit(obj);
    }
}

【讨论】:

    【解决方案2】:

    您无法使用标准的lock() 语句轻松地做到这一点。您可以使用Monitor.TryEnter() 尝试进入锁,然后如果该方法返回false,则记录一些内容。

    【讨论】:

      【解决方案3】:

      您为什么要这样做?如果是出于调试或分析目的,您可以使用非托管 CLR 分析或调试 API。另一个想法是在使用 PostSharp 或 Afterthought 等工具编译后静态修改 IL 代码。 (请注意,Afterthought 无法以当前形式执行此操作,但由于您有源代码,因此您可以破解它。)

      我建议您改为修改您的代码。我推荐这个而不是 dtb 的语法:

      if (!Monitor.TryEnter(x))
      {
          Log();
          Monitor.Enter(x);
      }
      try
      {
          //do work on a collection
      }
      finally
      {
          Monitor.Exit(x);
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-08-26
        • 2012-07-05
        相关资源
        最近更新 更多