首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用内存屏障的线程安全事件

使用内存屏障的线程安全事件
EN

Stack Overflow用户
提问于 2014-07-15 21:41:03
回答 1查看 132关注 0票数 1

在以下文章中,Stephen向我们提供了如何使threadsafe事件发生的建议:

http://www.codeproject.com/Articles/37474/Threadsafe-Events.aspx

作者在解决方案2中解释了以下代码错误的原因:

代码语言:javascript
复制
MyEventHandler myEvent = this.MyEvent;
if (myEvent != null)
{
    myEvent(this, args);
}

事件委托的副本可能已过时.Stephen提供了以下解决该问题的解决方案。

为了确保读取非易失性字段的当前值,必须发出内存屏障或将复制操作包装在锁中(并且必须是事件添加/删除方法获得的相同锁),而不必进入痛苦的详细级别。

我对他没有解释的细节很感兴趣。从技术上讲,在这里使用内存屏障会发生什么?与上述方法有什么不同?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-07-15 21:47:20

您发布的代码的问题是,编译器/jitter/cpu可能会重新排序this.MyEvent字段的读取,并将其移回时间。换句话说,您可能会看到刚才读取的缓存值。

为了防止这种重新排序,您可以发出一个内存屏障(也称为全内存围栏),它告诉所有三个参与者不要在栅栏上方(或下方)移动任何指令。这将防止读取被缓存,或与其他先前的读取“合并”。

代码语言:javascript
复制
Thread.MemoryBarrier();

//--> no instructions can be moved above or below the fence <--

MyEventHandler myEvent = this.MyEvent;
if (myEvent != null)
{
    myEvent(this, args);
}

另外,注意那个博客上的日期,它已经很古老了。事件从那时起就在C# 4.0的版本中被重写了。

Stephen认为事件是使用lock (this)实现的前提不再正确。事件现在是无锁的。您可以在这里看到由Chris:在C# 4的第一部分:锁中,事件得到了一点改进详细介绍的内容。

您也可能有兴趣阅读本系列的其他三个部分:

  • 事件在C# 4 (第2部分:语义变化和+=/-= )中得到了一些改进。
  • 事件在C# 4,第三部分:中断更改中进行了一些彻底的修改
  • 事件在C# 4中得到了一点改进,之后:有效事件
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24768691

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档