如果使用EventWaitHandel,从另一个线程读取时,从一个线程分配的变量是“线程安全的”吗?

时间:2014-02-21 08:56:42

标签: c# multithreading .net-4.0 event-wait-handle

如果我在一个线程上创建变量,则使用ManualResetEvent的{​​{1}}方法阻塞,直到另一个线程为同一个变量赋值并发出WaitOne()信号。当我来读取第一个线程上的变量时,我保证总是得到刚刚由另一个线程分配的值?

(我担心由于一些优化,我无法从CPU缓存中获取值,因为据我所知,我没有使用任何内存屏障。)

e.g。

EventWaitHandel

2 个答案:

答案 0 :(得分:1)

这些指令不会重新排序,这意味着,在生成线程上,字段分配将始终在发出句柄之前发生,并且在消费线程上,字段将始终为在处理信号后读取

如果这两对指令中的任何一对都可以重新排序(例如,如果第二个线程可以在之前读取字段,则表示信号已经发出信号),那么你将看到正确的值。

WaitOne()引入了一个隐式内存屏障,为您提供所需的获取释放语义。

Brian Gideon和Hans Passant在.NET框架中汇总了一个很好的列表,列出了隐含的内存障碍:Memory barrier generators

更多信息:Acquire and release semantics / Acquire and release fences

答案 1 :(得分:0)

您的变量是捕获的变量,即编译器将此局部变量转换为编译器生成的类的字段,因为您在lambda表达式中使用它。 Afaik,这些编译器生成的字段未标记为volatile,因此可以缓存它们。

编辑:事实上,这个领域并不是不稳定的。

你绝对可以通过编写自己的类来阻止缓存,这样编译器就不必创建一个。但是,这当然会妨碍您的代码的简洁性。