我想知道开发人员应该遵循何时(以及何处)放置锁定的指导原则。
例如:我理解应锁定此类代码,以避免另一个线程意外更改SomeHeapValue值的可能性。
class Foo
{
public SomeHeapObject myObject;
public void DoSummat(object inputValue_)
{
myObject.SomeHeapValue = inputValue_;
}
}
然而,我的问题是,锁定有多深?例如,如果我们有这个代码:
class Foo
{
public SomeHeapObject myObject;
public void DoSummat(object inputValue_)
{
myObject.SomeHeapValue = GetSomeHeapValue();
}
}
我们应该锁定DoSummat(...)方法,还是应该锁定GetSomeHeapValue()方法?
在编写多线程代码时是否有任何指导原则?
答案 0 :(得分:22)
我发现锁定和线程的最佳指南是这个页面(这是我在处理锁定和线程时所咨询的文本):
哟想要“锁定和线程安全”这一段,但也读了其余部分,它写得非常好。答案 1 :(得分:3)
尽可能少地锁定,但需要尽可能多。
尽可能避免锁定 - 在.NET 4.0中,有一些替代方法不会导致上下文切换。
尽量不要多次锁定。相应地构建您的API。例如一个队列。 DeQueue - 制作一个替代的DeQueue(int amount),可以通过一次锁定使许多物品出局。
答案 2 :(得分:0)
以下是一些针对多线程新手的指南:
标识程序的可变¹共享²状态。在应用程序的生命周期中,多个线程可以同时或顺序访问哪些可变变量,对象,属性和字段?
使用lock
保护对可变共享状态的所有访问。写入和读操作均应受到保护。指向程序的可变共享状态的单个不受保护的入口点就足以使锁定方案无效,并使程序的行为不确定。
使用单个储物柜对象保护所有可变的共享状态。仅当每个储物柜保护完全独立的可变共享状态孤岛时,才使用多个储物柜。
尽快释放锁。确保受保护区域仅包括在共享和可变状态下的操作。在这些区域内,请勿执行与此状态无关的任何操作。
如果您遵循这些准则,则可以对程序的正确性进行推理,并且您的程序将运行得很好。
所有这些准则都是可弯曲的,出于性能,便利或其他原因,多线程专家可以不总是在所有情况下都遵循它们,从而摆脱困境。但是,在正确判断是否可以安全地遵循任何这些准则之前,必须具备丰富的经验。因此请注意不要过早对自己过分自信!
¹可更改,不是只读的。
²由多个线程共享。