C# 中的 'volatile' 关键字仍然被破坏吗?

2024-03-02

乔·阿尔巴哈里有一个很棒的系列 http://www.albahari.com/threading/关于多线程,这是必读的内容,对于任何从事 C# 多线程处理的人来说都应该牢记于心。

然而,在第 4 部分中,他提到了 volatile 的问题:

请注意,应用 volatile 并不会阻止随后执行的写入操作 从交换中读取,这可能会产生脑筋急转弯。乔·达菲 下面的例子很好地说明了这个问题:如果 Test1 和 Test2 在不同线程上同时运行,有可能 b 都以 0 值结束(尽管在 x 和 y)

随后附注MSDN文档不正确:

MSDN 文档指出,使用 volatile 关键字可确保 现场始终存在最新值。 这是不正确的,因为正如我们所见,先写后读可以 被重新排序。

我已经检查过MSDN 文档 https://msdn.microsoft.com/en-us/library/x13ttww7.aspx,最后一次更改是在 2015 年,但仍然列出了:

volatile 关键字表示字段可能会被修改 同时执行的多个线程。字段是 声明的 volatile 不受编译器优化的影响 假设由单线程访问。这确保了最 现场始终存在最新值.

现在我仍然避免使用 volatile,而是使用更详细的方式来防止线程使用过时的数据:

private int foo;
private object fooLock = new object();
public int Foo {
    get { lock(fooLock) return foo; }
    set { lock(fooLock) foo = value; }
}

由于有关多线程的部分是在 2011 年编写的,所以这个论点今天仍然有效吗?是否仍应不惜一切代价避免使用易失性,转而使用锁或完整内存栅栏,以防止引入非常难以产生的错误(如上所述,这些错误甚至依赖于其运行的 CPU 供应商)?


当前实施中的不稳定因素是not尽管流行的博客文章声称有这样的事情,但还是坏了。然而,它的指定很糟糕,并且在字段上使用修饰符来指定内存排序的想法并不是那么好(将 Java/C# 中的 volatile 与 C++ 的原子规范进行比较,后者有足够的时间从早期的错误中吸取教训)。另一方面,MSDN 文章显然是由一个无权谈论并发的人写的,完全是伪造的。唯一明智的选择就是完全忽略它。

不稳定的担保获取/释放语义访问该字段时,只能应用于允许的类型原子读写。不多也不少。这足以有效地实现许多无锁算法,例如非阻塞哈希图 https://github.com/boundary/high-scale-lib.

一个非常简单的示例是使用易失性变量来发布数据。由于 x 上的 volatile,以下代码片段中的断言无法触发:

private int a;
private volatile bool x;

public void Publish()
{
    a = 1;
    x = true;
}

public void Read()
{
    if (x)
    {
        // if we observe x == true, we will always see the preceding write to a
        Debug.Assert(a == 1); 
    }
}

易失性并不容易使用,在大多数情况下,您最好采用一些更高级别的概念,但是当性能很重要或者您正在实现一些低级数据结构时,易失性可能非常有用。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C# 中的 'volatile' 关键字仍然被破坏吗? 的相关文章

  • Directory.Delete 之后 Directory.Exists 有时返回 true ?

    我有非常奇怪的行为 我有 Directory Delete tempFolder true if Directory Exists tempFolder 有时 Directory Exists 返回 true 为什么 可能是资源管理器打开了
  • 确保 StreamReader 不会挂起等待数据

    下面的代码读取从 tcp 客户端流读取的所有内容 并且在下一次迭代中它将仅位于 Read 上 我假设正在等待数据 我如何确保它不会在没有任何内容可供读取时返回 我是否必须设置低超时 并在失败时响应异常 或者有更好的办法吗 TcpClient
  • 计算 Richtextbox 中所有单词的最有效方法是什么?

    我正在编写一个文本编辑器 需要提供实时字数统计 现在我正在使用这个扩展方法 public static int WordCount this string s s s TrimEnd if String IsNullOrEmpty s re
  • 在 DataView 的 RowFilter 中选择 DISTINCT

    我试图根据与另一个表的关系缩小 DataView 中的行范围 我使用的 RowFilter 如下 dv new DataView myDS myTable id IN SELECT DISTINCT parentID FROM myOthe
  • 在 LINQ 中按 Id 连接多表和分组

    我想按categoryId显示列表产品的名称组 这是我的代码 我想要我的视图显示结果 Desktop PC HP Red PC Dell Yellow PC Asus Red SmartPhone Lumia 720 Blue 我的组模型
  • 如何创建包含 IPv4 地址的文本框? [复制]

    这个问题在这里已经有答案了 如何制作一个这样的文本框 我想所有的用户都见过这个并且知道它的功能 您可以使用带有 Mask 的 MaskedTestBox000 000 000 000 欲了解更多信息 请参阅文档 http msdn micr
  • 获取两个工作日之间的天数差异

    这听起来很简单 但我不明白其中的意义 那么获取两次之间的天数的最简单方法是什么DayOfWeeks当第一个是起点时 如果下一个工作日较早 则应考虑在下周 The DayOfWeek 枚举 http 20 20 5B1 5D 3a 20htt
  • 是否有实用的理由使用“if (0 == p)”而不是“if (!p)”?

    我倾向于使用逻辑非运算符来编写 if 语句 if p some code 我周围的一些人倾向于使用显式比较 因此代码如下所示 if FOO p some code 其中 FOO 是其中之一false FALSE 0 0 0 NULL etc
  • DbContext 和 ObjectContext 有什么区别

    From MSDN 表示工作单元和存储库模式的组合 使您能够查询数据库并将更改分组在一起 然后将这些更改作为一个单元写回存储 DbContext在概念上类似于ObjectContext 我虽然DbContext只处理与数据库的连接以及针对数
  • 如何检测表单的任何控件的变化?

    如何检测 C 中表单的任何控件的更改 由于我在一个表单上有许多控件 并且如果表单中的任何控件值发生更改 我需要禁用按钮 我正在寻找一些内置函数 事件处理程序 属性 并且不想为此创建自定义函数 不 我不知道任何时候都会触发任何事件any控制表
  • 如何在 32 位或 64 位配置中以编程方式运行任何 CPU .NET 可执行文件?

    我有一个可在 32 位和 64 位处理器上运行的 C 应用程序 我试图枚举给定系统上所有进程的模块 当尝试从 64 位应用程序枚举 32 位进程模块时 这会出现问题 Windows 或 NET 禁止它 我认为如果我可以从应用程序内部重新启动
  • 如何在 Xaml 文本中添加电子邮件链接?

    我在 Windows Phone 8 应用程序中有一些大文本 我希望其中有电子邮件链接 例如 mailto 功能 这是代码的一部分
  • Android 中的处理程序与异步调用

    目前我正在使用处理程序来调用 Web 服务方法以使其在后台运行 问题是它需要更多的时间来给出响应 在性能方面似乎更昂贵 现在我计划使用异步调用 哪一个是最好的 Android 中的处理程序和异步调用有什么区别 请帮我想出一个最好的解决方案
  • 使用自定义堆的类似 malloc 的函数

    如果我希望使用自定义预分配堆构造类似 malloc 的功能 那么 C 中最好的方法是什么 我的具体问题是 我有一个可映射 类似内存 的设备 已将其放入我的地址空间中 但我需要获得一种更灵活的方式来使用该内存来存储将随着时间的推移分配和释放的
  • C#:帮助理解 UML 类图中的 <>

    我目前正在做一个项目 我们必须从 UML 图编写代码 我了解 UML 类图的剖析 但我无法理解什么 lt
  • 按 Esc 按键关闭 Ajax Modal 弹出窗口

    我已经使用 Ajax 显示了一个面板弹出窗口 我要做的是当用户按 Esc 键时关闭该窗口 这可能吗 如果有人知道这一点或以前做过这一点 请帮助我 Thanks 通过以下链接 您可以通过按退出按钮轻松关闭窗口 http www codepro
  • 不同类型指针之间的减法[重复]

    这个问题在这里已经有答案了 我试图找到两个变量之间的内存距离 具体来说 我需要找到 char 数组和 int 之间的距离 char data 5 int a 0 printf p n p n data 5 a long int distan
  • System.IO.FileNotFoundException:找不到网络路径。在 Windows 7 上使用 DirectoryEntry 对象时出现异常

    我正在尝试使用 DirectoryEntry 对象连接到远程 Windows 7 计算机 这是我的代码 DirectoryEntry obDirEntry new DirectoryEntry WinNT hostName hostName
  • C++ 条件编译

    我有以下代码片段 ifdef DO LOG define log p record p else define log p endif void record char data 现在如果我打电话log hello world 在我的代码中
  • 如何将 PostgreSql 与 EntityFramework 6.0.2 集成? [复制]

    这个问题在这里已经有答案了 我收到以下错误 实体框架提供程序类型的 实例 成员 Npgsql NpgsqlServices Npgsql 版本 2 0 14 2 文化 中性 PublicKeyToken 5d8b90d52f46fda7 没

随机推荐

  • Asp.Net MVC 每个请求的唯一 ID

    在我们的 MVC 5 站点中 没有会话 我们需要为每个请求获取 生成一个唯一的 ID 这将用作记录请求中所有活动的 ID 有没有办法为请求分配 获取值以启用此功能 将其添加到请求项集合 odetocode com articles 111
  • iOS 7、iPhone、接近传感器

    这是一个简短的问题 但它困扰了我整整一个晚上 我这里有一些自己的应用程序 我只编写 Objective C 并且使用 ARC 如果我在 appDelegate 中编写 application didFinishLaunching UIDev
  • JavaScript 实例化

    你能在下面的例子中告诉我为什么吗sub instanceof Super is false function Super var obj prop1 value1 return obj var sub new Super sub insta
  • 带变量的 iframe 源

    我有一些问题 Is 与 HTMLIFrameElement 相同吗 Why 工作正常 但是 a document getElementsByTagName body 0 b document createElement iframe b s
  • 模块“PDO”已加载到未知行 0

    我将 nginx 与 php5 fpm 一起使用 由于某种原因 我的 php5 fpm 一直说 模块 PDO 已经加载到未知的第 0 行 老实说 我不知道为什么 该扩展不会加载到 php ini 内部 而是从 with config fil
  • 溢出隐藏隐藏下拉菜单,但将溢出隐藏隐藏在隐藏导航背景中

    首先 这是一个 js 小提琴 http jsfiddle net B6DSv http jsfiddle net B6DSv 我遇到的问题是我的 css nav overflow hidden THIS LINE background co
  • ASP.NET WebApi DateTimeOffset 序列化为 Json/JavaScript (angular2)

    我没有找到一个很好的方法来获取 JavaScript Angular2 的 DateTimeOffset 值 我正在使用 WebApi 5 2 3 和 angular2 在网上我看到日期如下 RecordModifiedAt 2016 03
  • OpenGL ES 2.0 中的光线拾取

    我正在尝试在 OpenGL ES 2 0 中实现光线拾取以确定是否已单击对象 到目前为止 我只是想检查是否已按下特定的三角形 我使用这个网站作为动力http android raypick blogspot ca 2012 04 first
  • CodeIgniter 仅允许在登录时访问某些控制器

    我有一些 CodeIgniter 控制器 只能由已登录的用户访问 即 this gt session gt userdata username 不为空 如果未经身份验证的人尝试访问所述控制器 他们应该收到 header location a
  • chromedriver:ubuntu 14.04 64 位上缺少各种 lib 依赖项

    所以我尝试运行从下载的 chromedriver 2 20 wget http chromedriver storage googleapis com 2 20 chromedriver linux64 zip 在我的 ubuntu 14
  • 如何向 UILabel 添加填充? [复制]

    这个问题在这里已经有答案了 UILabel 内的文本与左边框和右边框相冲突 有没有办法向 UILabel 添加一些内部填充 以便文本不会如此紧密地接触内部边框 只需调整标签的位置 我不知道任何其他方法 尽管其他人可能会 如果您对背景颜色有疑
  • OpenXML:Excel 中自动调整列宽

    我已经编写了使用 OpenXML 生成 Excel 文件的代码 下面是在 Excel 中生成列的代码 Worksheet worksheet new Worksheet Columns columns new Columns int num
  • HistoryRecord 的活动空闲超时?

    W ActivityManager 81 Launch timeout has expired giving up wake lock W ActivityManager 81 Activity idle timeout for Histo
  • log4j:记录包,但不包括其子包

    您好 我想排除某些子包被我的一个记录器记录 因为它们正在被另一个记录器记录 例如 com mysite app logger1 com mysite app news logger2 com mysite app events logger
  • 如何使用 ASP.NET MVC 将字典绑定到一组复选框?

    我的需要是 绑定 Dictionary
  • Maven 的 Jersey 问题 - Shade 插件

    我的问题非常类似于 仅当依赖项组装到单个 jar 中时才会抛出 Jersey 异常 https stackoverflow com questions 12611213 jersey exception only thrown when d
  • 过滤R中所有列包含相同数据的行

    我有一个数据集 要求每个参与者回答一系列问题 有些人对每个问题都给出了相同的回答 我想丢弃这些参与者的数据 但不知道如何去做 我的意思是我可以尝试过滤 区分 但我遇到的问题是大约有 100 个问题 所以 100 列 我不确定使 R 过滤所有
  • 使用PHP 5.5的password_hash和password_verify函数

    假设我想存储用户的密码 这是否是使用 PHP 5 5 的正确方法password hash 函数 或 PHP 5 3 7 的此版本 https github com ircmaxell password compat https githu
  • 我在 Visual Studio 2010 中找不到从工具菜单生成本地资源

    我在网页的设计视图 标记 中 我在工具菜单中找不到 生成本地资源 谁能告诉我如何启用这个工具 查看 aspx 或 ascx 文件时 确保您正在查看 设计 或 拆分 选项卡 而不是 源 选项卡 此外 这篇文章可能会有所帮助 其中部分指出 如果
  • C# 中的 'volatile' 关键字仍然被破坏吗?

    乔 阿尔巴哈里有一个很棒的系列 http www albahari com threading 关于多线程 这是必读的内容 对于任何从事 C 多线程处理的人来说都应该牢记于心 然而 在第 4 部分中 他提到了 volatile 的问题 请注