首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Do接口有助于避免.NET应用程序中的死锁

问Do接口有助于避免.NET应用程序中的死锁
EN

Stack Overflow用户
提问于 2014-01-08 09:13:29
回答 3查看 74关注 0票数 0

我试图了解我的应用程序是否因为缓慢的I/O (计算开销很大的算法)或对资源的互斥访问而挂起。在这种情况下,使用接口并在可能导致锁定的类中实现它们,可能会避免锁定或不锁定。

我知道Interface是一种编程结构,在这种结构中,我们定义了我们希望公开给公共或其他模块的函数/服务,并避免循环依赖。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-01-08 09:36:53

不,接口与死锁完全无关。如果您有一个死锁,那么根据定义,这是因为对共享资源的同步访问不会减慢I/O):

死锁是这样一种情况,即两个或多个相互竞争的动作都在等待对方完成,因此两者都没有。

如何调试?

死锁可能有很多原因(当然,某些条件--慢I/O、CPU密集型算法--可能会导致死锁出现得更频繁,但它们并不是造成死锁的原因)。

大多数情况下,如果可以将调试器附加到应用程序,则很容易检测到它们。挂起时暂停执行,查看线程列表和它们的堆栈,您可以看到它们是否在等待共享资源。

一个非常常见的死锁场景是:

  • 线程1获取资源A上的锁。
  • 线程2获取资源B上的锁。
  • 线程1试图获取资源B上的锁,但是它被线程2锁定,然后线程1将被挂起(稍微简化一点)。
  • 线程2试图获取资源A上的锁,但是它被线程1锁定,那么线程2将被挂起。
  • 两个线程都挂起,就不能释放它们获得的锁。如果没有超时,那么这个条件就不会得到解决(应用程序或其中的一部分可能会挂起)。

另一种非常常见的情况是:

  • 线程1获取资源A上的锁(例如,在C#中不使用lock语句,而是直接使用Monitor.Enter()或其他同步原语(如ReadWriterLockSlim) )。
  • 由于异常,执行失败。异常被处理,但是锁没有被释放。
  • 第一次,当另一个线程(如果锁支持重入)尝试使用相同的锁时,应用程序将挂起(因为锁从未被释放)。

这是一个代码示例(我知道非常天真的锁机制):

代码语言:javascript
复制
object _syncRoot = new object();

void ThreadWorker(object state ) {
    Monitor.Enter(_syncRoot);

    try {
        // Do some operation that may fail

        // Release lock
        Monitor.Exit(_syncRoot);
    }
    catch (Exception e) {
        // Log error
    }
}

幸运的是,这是非常容易避免的(检查这个答案以查看锁如何实现监视器)。

代码语言:javascript
复制
try {
    lock (_syncRoot) {
        // Do your job here   
    }
}

在以前的场景中,如果重新访问此锁(但其他线程将挂起)相同的线程不会挂起,但是如果您使用的是读/写锁,那么它就会挂起(或者如果它不支持重入,请参阅这个问题了解其他细节)。如果您对锁使用超时(当然,这并不总是可能的),则可能会检测到这种故障。当锁尝试超时时,应用程序将检测到它并采取适当的操作(如果有的话,它甚至可以优雅地中止)。

票数 1
EN

Stack Overflow用户

发布于 2014-01-08 09:32:58

不是的。相反,由于接口隐藏了实现,所以很难看到导致问题的锁。

使用调试器的Debug + Windows + Threads查看哪些线程正在运行,哪些线程正在执行获取锁的代码。您还可以看到拥有锁的线程的线程ID,请检查这个答案。

票数 4
EN

Stack Overflow用户

发布于 2014-01-08 09:44:28

接口不会改变代码在运行时执行的内容。锁定纯粹是运行时的事情。对于死锁,只有实际执行的代码才重要。如何调用方法并不重要。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20991257

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档