什么时候可以锁定(syncObject)抛出异常?

时间:2009-11-28 14:36:59

标签: .net multithreading synchronization locking com-interop

我在.NET中编写了一个com组件,如果我试图锁定任何方法中的任何对象(由与我的com组件通信的非托管代码调用),我会得到一个异常。

此时我没有确切的异常文本,但也没有多大帮助。

所以我的问题是在什么情况下锁(syncObject)会抛出异常? 以下是一些事实:

  • syncObject不为空
  • syncObject尚未锁定

它与在(单线程公寓)或MTA(多线程公寓)中运行的被叫者有什么关系吗?

1 个答案:

答案 0 :(得分:2)

来自this page

  

每次锁定获取都可能引发异常。做好准备。

     

如果锁定获取遇到争用(包括CLR监视器),大多数锁定会懒惰地分配事件。在低资源条件下,此分配可能会失败,从而导致OOM源自锁的入口。 (请注意,典型的非阻塞自旋锁不会因OOM而失败,这允许它在一些资源受限的情况下使用,例如CER内部。)类似地,像SQL Server这样的主机可以执行死锁检测甚至打破这些死锁生成源自Enter语句的异常,表现为System.Runtime.InteropServices.COMException。

     

通常没有太多可以回应这样的例外。但是,必须严格处理故障的可靠性和安全敏感代码应该考虑这种情况。我们本来希望主机死锁可以智能地响应,但大多数库代码无法智能地展开到堆栈上的安全点,以便它可以退回并重试操作。在典型的堆栈上存在太多的跨库混合。这就是为什么使用TryEnter进行基于超时的Monitor采集通常是防止死锁的好主意。

因此,您可以阅读,似乎在资源受限的条件下,我们可能会从监视器的Enter方法抛出异常,其中锁(o)在内部使用。

所以也许你的解决方案就像旋转等待?

{
    uint iters = 0;
    while (!cond) {
        if ((++iters % 50) == 0) {
            // Every so often we sleep with a 1ms timeout (see #30 for justification).
            Thread.Sleep(1);
        } else if (Environment.ProcessorCount == 1) {
            // On a single-CPU machine we yield the thread.
            Thread.Sleep(0);
        } else {
            // Issue YIELD instructions to let the other hardware thread move.
            Thread.SpinWait(25);
        }
    }
}

cond可能是某些

private volatile int cond = 0

用于例如Interlocked.CompareExchange,您将其更改为例如Thread.Current.ManagedThreadID还是其他非零的东西?