我正在阅读this MSDN article on lockless thread syncing。这篇文章似乎推断,只要你在访问共享变量之前输入一个锁,那么这些变量将是最新的(至少在.Net 2.0中)。
我想到这是怎么可能的? .Net中的锁只是所有线程在访问内存之前检查的任意对象,但锁本身并不知道正在访问的内存位置。
如果我有一个线程更新变量,甚至是整块内存,那么当进入/退出锁时,这些更新如何保证从CPU缓存中刷新?所有内存访问是否在锁内有效地变为易失性?
答案 0 :(得分:5)
检查Eric Lippert的工作:http://blogs.msdn.com/b/ericlippert/archive/2011/06/16/atomicity-volatility-and-immutability-are-different-part-three.aspx
锁定保证锁内部读取或修改的内存一致,锁定保证一次只有一个线程访问给定的内存块,依此类推。
所以是的,只要您在访问共享资源之前每次都锁定,您就可以非常确定它是最新的
编辑查看以下帖子以获取更多信息和非常有用的概述:http://igoro.com/archive/volatile-keyword-in-c-memory-model-explained/
答案 1 :(得分:1)
嗯,文章解释道:
在输入锁定之前,读取无法移动。
- 醇>
退出锁定后,写入无法移动。
来自同一篇文章的更多解释:
当线程退出锁定时,第三个规则确保在保持锁定时进行的任何写入对所有处理器都是可见的。在另一个线程访问内存之前,读取线程将进入锁定,第二个规则确保在锁定后逻辑上发生读取。
答案 2 :(得分:1)
并非所有c#内存读写都是易失性的,不是。 (想象一下,如果情况表现如此!)
但是
在进入/退出锁定时,如何保证从CPU缓存中刷新这些更新
CPU缓存是CPU特定的,但它们都具有某种形式的memory coherence protocol。也就是说,当您从核心访问某些内存时,如果它存在于另一个核心缓存中,则CPU使用的协议将确保将数据传递到本地核心。
Petar Ivanov在他的回答中暗示的是非常相关的。如果您想了解更多他的观点,您应该查看memory consistency model。
现在,C#如何保证内存是最新的取决于C#实现者,Eric Lippert的博客当然是理解潜在问题的好地方。
答案 3 :(得分:0)
我不确定.NET中的事态,但是在Java中明确指出,以这种方式合作的任何两个线程必须使用相同的对象进行锁定才能从您在介绍性陈述中所说的内容中获益,而不仅仅是锁定。这是一个至关重要的区别。
锁不需要“知道”它所保护的内容;它只需要确保前一个储物柜所写的所有物品都可以在另一个储物柜继续使用之前使用。