如果我在一个线程上创建变量,则使用ManualResetEvent
的{{1}}方法阻塞,直到另一个线程为同一个变量赋值并发出WaitOne()
信号。当我来读取第一个线程上的变量时,我保证总是得到刚刚由另一个线程分配的值?
(我担心由于一些优化,我无法从CPU缓存中获取值,因为据我所知,我没有使用任何内存屏障。)
e.g。
EventWaitHandel
答案 0 :(得分:1)
这些指令不会重新排序,这意味着,在生成线程上,字段分配将始终在发出句柄之前发生,并且在消费线程上,字段将始终为在处理信号后读取。
如果这两对指令中的任何一对都可以重新排序(例如,如果第二个线程可以在之前读取字段,则表示信号已经发出信号),那么你将不看到正确的值。
WaitOne()
引入了一个隐式内存屏障,为您提供所需的获取释放语义。
Brian Gideon和Hans Passant在.NET框架中汇总了一个很好的列表,列出了隐含的内存障碍:Memory barrier generators
更多信息:Acquire and release semantics / Acquire and release fences
答案 1 :(得分:0)
您的变量是捕获的变量,即编译器将此局部变量转换为编译器生成的类的字段,因为您在lambda表达式中使用它。 Afaik,这些编译器生成的字段未标记为volatile
,因此可以缓存它们。
你绝对可以通过编写自己的类来阻止缓存,这样编译器就不必创建一个。但是,这当然会妨碍您的代码的简洁性。