2009-08-19 117 views
45

有什么方法可以确定一个对象是否被锁定在C#中?我有一个难以置信的地位,通过设计,我正在从一个班级里的一个队列里读书,我需要将这些内容转储到班级中的一个集合中。但是该集合也可以从类外部的接口读取/写入。所以显然可能会出现集合正在写入的情况,同时我想写入该集合。有没有办法检测对象是否被锁定?

我可以对它进行编程,比如使用委托,但它会很难看。

+0

是的, 谢谢大家。这几乎证实了我的想法。 – 2009-08-19 15:14:08

回答

40

您可以始终使用Monitor class上的静态TryEnter method呼叫等待值为0。如果它被锁定,则该呼叫将返回错误。

但是,这里的问题是,您需要确保您尝试同步访问权限的列表被锁定在自身上,以同步访问权限。

通常不好的做法是使用正在同步访问的对象作为锁定对象(暴露对象的内部细节太多)。

请记住,锁可以在其他任何东西上,所以只要在列表中调用它就没有意义,除非您确定该列表是被锁定的。

10

Monitor.TryEnter如果对象没有被锁定就会成功,如果此时对象被锁定,将返回false。但是请注意,这里存在隐式竞争:此方法返回的实例,对象可能不再被锁定。

6

当前您可以调用Monitor.TryEnter来检查对象是否被锁定。

在.NET CLR 4.0团队将添加 “锁定检查API”

这里是Rick Byers文章报价:

锁检查
我们增加了一些简单的API到ICorDebug,它允许您探索托管锁(监视器)。例如,如果线程被阻塞等待锁定,您可以找到其他线程当前正在锁定的锁定(以及是否有超时)。

所以,用这个API,你将能够检查:
1)什么对象是持有锁?
2)谁在等待?

希望这会有所帮助。

+0

有趣。 鲍勃。 – 2009-08-19 15:03:30

7

我不知道如果一个静态调用TryEnter的时间为0将保证锁定将不被获取,如果它是可用的。我确实在调试模式下,测试溶液中的同步变量使用以下被锁定:

#if DEBUG 
// Make sure we're inside a lock of the SyncRoot by trying to lock it. 
// If we're able to lock it, that means that it wasn't locked in the first 
// place. Afterwards, we release the lock if we had obtained it. 
bool acquired = false; 
try 
{ 
    acquired = Monitor.TryEnter(SyncRoot); 
} 
finally 
{ 
    if (acquired) 
    { 
     Monitor.Exit(SyncRoot); 
    } 
} 
Debug.Assert(acquired == false, "The SyncRoot is not locked."); 
#endif 
+2

变量'isNotLocked'被命名得相当糟糕。如果'isNotLocked'为真,则解锁 - 虽然从技术上讲它是正确的,因为当锁成功获取时,isNotLocked将成立,上面的代码真的不好阅读。如果有其他人必须在此工作,他将有一个WTF时刻。 – ChrisWue 2013-10-20 20:12:01

+2

如果运行的线程是拥有该锁的线程,则不起作用。它会说锁是免费的,但事实并非如此。 – 2014-09-19 17:34:42

相关问题