你应该在读取值时锁定资源吗?

时间:2009-01-10 15:43:36

标签: c# .net multithreading synchronization

在C#中进行线程同步时,我还应该在读取值或仅更改它时锁定对象吗?

例如我有队列< T>宾语。我应该在执行Enqueue和Dequeue时锁定它还是在检查像Count这样的值时是否也应该锁定它?

4 个答案:

答案 0 :(得分:3)

来自MSDN:

  

队列<(<(T>)>)可以支持   同时多个读者,同样长   因为集合没有被修改。   即便如此,通过一个列举   集合本质上不是一个   线程安全的程序。保证   在枚举期间线程安全,你   可以锁定集合   整个枚举。允许的   要由多个访问的集合   阅读和写作的线索,你   必须实现自己的   同步。

在项目排队时,您应确保没有读者处于活动状态(锁定可能是一个好主意)。

查看反射器中的计数会显示私有字段的读数。这可以是好的,具体取决于您对值的处理方式。这意味着你不应该做这样的事情(没有适当的锁定):

if(queue.Count > 0)
    queue.Dequeue();

答案 1 :(得分:2)

取决于你想用锁做什么。通常这种锁定需要读写器锁定机制。

读者/作者锁定意味着读者共享一个锁,因此您可以让多个读者同时阅读该集合,但是要写,您应该获得一个独占锁。

答案 2 :(得分:1)

如果您没有锁定它,您可能会获得较旧的值。可能发生竞争条件,使得执行写入操作改变计数,但是在更改之前,您将获得值。例如,如果队列只有一个项目,并且一个线程调用了dequeue,则另一个线程可以读取计数,找到它仍为1,然后再次调用dequeue。在授予锁定之前,第二次调用不会完成,但那时队列实际上是空的。

答案 3 :(得分:0)

CLR保证原子读取的值高达处理器的宽度。因此,如果您在32位上运行,则读取int将是原子的。如果你在64位机器上运行,那么读取long将是原子的。例如,如果CountInt32,则无需锁定。

This post与您的问题相关。