在C#中进行线程同步时,我还应该在读取值或仅更改它时锁定对象吗?
例如我有队列< T>宾语。我应该在执行Enqueue和Dequeue时锁定它还是在检查像Count这样的值时是否也应该锁定它?
答案 0 :(得分:3)
来自MSDN:
队列<(<(T>)>)可以支持 同时多个读者,同样长 因为集合没有被修改。 即便如此,通过一个列举 集合本质上不是一个 线程安全的程序。保证 在枚举期间线程安全,你 可以锁定集合 整个枚举。允许的 要由多个访问的集合 阅读和写作的线索,你 必须实现自己的 同步。
在项目排队时,您应确保没有读者处于活动状态(锁定可能是一个好主意)。
查看反射器中的计数会显示私有字段的读数。这可以是好的,具体取决于您对值的处理方式。这意味着你不应该做这样的事情(没有适当的锁定):
if(queue.Count > 0)
queue.Dequeue();
答案 1 :(得分:2)
取决于你想用锁做什么。通常这种锁定需要读写器锁定机制。
读者/作者锁定意味着读者共享一个锁,因此您可以让多个读者同时阅读该集合,但是要写,您应该获得一个独占锁。
答案 2 :(得分:1)
如果您没有锁定它,您可能会获得较旧的值。可能发生竞争条件,使得执行写入操作改变计数,但是在更改之前,您将获得值。例如,如果队列只有一个项目,并且一个线程调用了dequeue,则另一个线程可以读取计数,找到它仍为1,然后再次调用dequeue。在授予锁定之前,第二次调用不会完成,但那时队列实际上是空的。
答案 3 :(得分:0)
CLR保证原子读取的值高达处理器的宽度。因此,如果您在32位上运行,则读取int
将是原子的。如果你在64位机器上运行,那么读取long
将是原子的。例如,如果Count
是Int32
,则无需锁定。
This post与您的问题相关。