锁定集合,然后创建集合的新实例。危险吗?

时间:2016-09-06 23:11:35

标签: c# multithreading list collections locking

我目前正在为一些硬件设备开发多线程接口,我将我的轮询数据包存储在List集合中。由于此接口需要非常线程安全,因此每次我想对其进行更改时都会锁定集合。我通过运行诊断发现,创建集合的新实例比清除它然后为轮询添加新的值范围要快得多。我想知道这样做是否会导致锁定问题,因为我对多线程应用程序的经验有限,甚至没有锁定集合而不是SyncRoot对象的经验。

以下是用于比较的示例代码段:

lock (Poll)
{
    Poll = new List<byte>(new byte[] { START, 0x00, STATUS_REQUEST, 0x00, 0x00});
}

...对战

lock (Poll)
{
    Poll.Clear();
    Poll.AddRange(new byte[] { START, ZERO, STATUS_REQUEST, ZERO, ZERO });
}

编辑:想要注意Poll对象没有公开曝光。这是禁忌。

1 个答案:

答案 0 :(得分:2)

由于您可能已经读过,因此您不应该锁定任何公共属性/ this跳过该部分问题。

lock(Poll) { Poll = new ... }是错的 - 甚至不尝试; lock (Poll) { Poll.Clear();...{反对&#34;不要锁定公共对象&#34;指导,但至少会达到预期的效果。

lock语句使用变量的当前值作为门,如果值稍后更改,则可能无法正确阻止另一个线程重新输入lock下的同一段代码。

lock(Poll) { Poll = new ... }将锁定Poll对象,并且在本地缓存具有相同对象的任何人都可以继续锁定并阻止重新输入此代码。只有lock(Poll) {...}的代码在分配时才能获得Poll变量的相同值,并且可能输入相同的代码块。

正确的代码:

object lockPoll = new object(); // stays the same over `Poll` property lifetime
...

lock(lockPoll)
{
   // code that accesses or changes Poll 
   // both Poll = new ... or Poll.Clear() are fine
}