在查看一些旧代码时,我们遇到了以下代码:
lock (System.Threading.Thread.CurrentThread) // Critical Section - no interrupting.
我们的第一个反应是“WTF” - 代码锁定在当前线程上,这是每个线程上的一个不同的对象(除了在递归的情况下,这将是愚蠢的锁定,然后)。看起来这个锁没有任何用途。我们想知道这是否确实是WTF,或者它是否真的有用。
答案 0 :(得分:4)
它看起来就像是来自那行代码的WTF,但是如果线程对象被传递给其他线程并用作锁,那么这是有道理的。但是,使用线程作为锁定似乎是一种非常糟糕的做法。
答案 1 :(得分:2)
似乎Thread.Abort
的来电create a lock on the current thread。因此,似乎这可能是确保流程不被中断的一种方式(hacky,但它可能有效)。当然,它仍然是错误的(例如,如果电力耗尽);但也许这就是它正在尝试做的事情。当然,为一个线程中止具有明确定义的退出点会好得多。但我认为这就是它正在做的事情(Thread.Abort
在我们的软件中非常普遍)。
答案 2 :(得分:1)
我会检查创建线程的代码,并查看线程对象的使用位置。也许主线程创建了许多后台线程,并在锁中使用线程对象。或者这是一个线程池线程?
无论如何,这不是一段非常好的代码:)
答案 3 :(得分:1)
除了浪费CPU,即使在递归中也没有任何效果。
lock()只会为每个线程提供独占锁,因此第二次访问对象锁的同一个线程不会停止。如果确实如此,你会遇到死锁情况,线程正在等待自己解锁,以便继续。
object someObj = new object();
lock (someObj) {
lock (someObj) {
// this code will execute even though it had to go through two locks on the same obj
}
}
答案 4 :(得分:0)
这听起来像是不好的做法,因为它可能会导致无意的同步。通常,您希望将同步代码隐藏在类的范围内,这样您就可以锁定非公共字段或属性。
特别是锁定
this
或公共静态API提供的其他对象,例如
Thread.CurrentThread
是一个坏主意,因为你的库的用户很容易错误地锁定同一个对象。
反过来也是如此,如果你有一个线程安全对象避免锁定对象本身(因为它可能在内部锁定),而是使用专用对象。如果需要从类外部同步,则可以公开专用对象。一个例子是
ICollection.SyncRoot