锁定变量时,必须将其锁定到处吗?

时间:2010-11-10 08:19:52

标签: c# multithreading

我想知道当从多个线程访问变量时,是否必须为每次访问锁定它?例如,我有一个列表变量,并希望在我从中删除项目时无法访问该列表。我必须锁定它,即使在只访问数据的线程中,或者足以将其锁定在“删除项目”线程中。我担心的是,如果一个线程访问列表在进程中间停止,则转到另一个从列表中删除并锁定变量的线程,将出现错误。

4 个答案:

答案 0 :(得分:13)

您的浴室门没有锁上。相反,它有一个双面标志,一边说“占用”,另一边说“没人”。当有人接近浴室时,如果它被标记为已占用,则等待它被标记为无人居住。如果它被标记为空闲,他们将标志设置为占用并进入。当他们离开时,他们将标志设置为无人居住。

(还必须有一些谈判机制来处理有两个或两个以上的人等待的情况 - 谁先进入?还有,当两个人同时接近一个未占用的浴室时会发生什么 - 谁赢了?但是我们会忽略那些皱纹;它们与这个类比没有密切关系。)

这个方案运作得很好。你的问题是“如果有人忽略了这个标志,或者忘了改变标志,我是否会遇到同时在浴室里有两个人的情况?”

是的,显然你可以。如果你不相信我,那么我鼓励你在浴室里尝试一下,看看当有人忽略这个协议时会发生什么。资源访问协议仅在所有人尊重协议时才保护对该资源的访问!

答案 1 :(得分:10)

如果您希望将集合保持在一致状态(或使用锁保护的任何其他对象),则必须锁定读取和写入。

有一些'例外',比如使用ReaderWriterSlimLock,您仍需要获取写入锁,但您可以有效地执行多线程读取:

  

使用ReaderWriterLockSlim来保护   由多个读取的资源   线程并由一个线程写入   一次。 ReaderWriterLockSlim允许   多线程处于读模式,   允许一个线程处于写入模式   独家拥有锁,   并允许一个已读取的线程   访问处于可升级的读取模式,   线程可以从哪个升级到   写模式而不必   放弃对它的读取权限   资源。

答案 2 :(得分:1)

我多次问自己这个问题并且意识到这个问题出现的那一刻,同步协议很可能被打破。在一个健全的同步学科中,甚至没有提出进行不受保护的访问的愿望。

我能想到的唯一例外是你有一些受锁保护的计数器,你只想检查它是否有统计/信息用途。如果您对此感兴趣并且您知道对您的特定平台和内存模型(以及甚至可以远程运行此特定软件的每个未来平台)读取/写入该计数器变量都是原子的,那么请随意无锁地进入柜台。第二个前提条件很难满足,所以你不应该这样做。

答案 3 :(得分:0)

在对象上使用lock并不能真正锁定对象。锁对象实际上只是一个标记,因此只要所有线程都同意同一个锁定对象来读取和写入所讨论的共享状态,就可以锁定任何对象。惯例是使用Object的私有只读实例并锁定它。