易失性、互锁性、锁定性

2023-12-07

假设一个类有一个public int counter由多个线程访问的字段。这int仅递增或递减。

要增加此字段,应使用哪种方法,为什么?

  • lock(this.locker) this.counter++;,
  • Interlocked.Increment(ref this.counter);,
  • 更改访问修饰符counter to public volatile.

现在我发现了volatile,我已经删除了很多lock声明和使用Interlocked。但有理由不这样做吗?


最差(实际上不起作用)

更改访问修饰符counter to public volatile

正如其他人所提到的,这本身实际上根本不安全。要点是volatile是在多个 CPU 上运行的多个线程可以并且将会缓存数据并重新排序指令。

如果是not volatile,并且 CPU A 递增一个值,那么 CPU B 可能直到一段时间后才真正看到该递增的值,这可能会导致问题。

如果是volatile,这只是确保两个CPU同时看到相同的数据。它根本不会阻止他们交错读取和写入操作,这是您试图避免的问题。

次好的:

lock(this.locker) this.counter++;

这样做是安全的(只要您记得lock您访问的其他任何地方this.counter)。它防止任何其他线程执行由以下代码保护的任何其他代码locker。 使用锁还可以防止上述多 CPU 重新排序问题,这很棒。

问题是,锁定速度很慢,如果你重复使用locker在其他一些并不真正相关的地方,那么您最终可能会无缘无故地阻塞其他线程。

Best

Interlocked.Increment(ref this.counter);

这是安全的,因为它可以有效地“一次点击”完成读取、增量和写入,并且不能被中断。因此,它不会影响任何其他代码,并且您也不需要记住在其他地方锁定。它也非常快(正如 MSDN 所说,在现代 CPU 上,这通常实际上是一条 CPU 指令)。

I'm not entirely sure however if it gets around other CPUs reordering things, or if you also need to combine volatile with the increment.

联锁注释:

  1. 互锁方法在任意数量的内核或 CPU 上同时都是安全的。
  2. 互锁方法在它们执行的指令周围应用完整的栅栏,因此不会发生重新排序。
  3. 联锁方法不需要甚至不支持访问易失性字段,因为易失性在给定字段的操作周围放置了半栅栏,而互锁则使用完整栅栏。

脚注: 挥发物实际上有什么用处。

As volatile不能防止此类多线程问题,它有什么用?一个很好的例子是,您有两个线程,其中一个总是写入变量(例如queueLength),以及始终从同一个变量读取的变量。

If queueLength不是易失性的,线程 A 可能会写入五次,但线程 B 可能会认为这些写入被延迟(甚至可能以错误的顺序)。

解决方案是锁定,但在这种情况下您也可以使用 volatile。这将确保线程 B 始终看到线程 A 写入的最新内容。但请注意,这个逻辑only如果你有从不读书的作家和从不写作的读者,and如果你正在写的东西是一个原子值。一旦执行了一次读-修改-写操作,您就需要进行互锁操作或使用锁。

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

易失性、互锁性、锁定性 的相关文章

  • 使用 C++ 拆分“[常规设置]”格式的节字符串

    我是 C 新手 我想读取包含部分和键值对的 ini 文件 根据部分 我想读取相应键的值 首先 我想阅读方括号内的部分 请帮忙 谢谢 对于真正的 INI 文件解析 我强烈建议iniparser库 http ndevilla free fr i
  • 每次调用新方法时触发事件

    我正在做一个logger for a c 应用程序需要记录每个方法被调用的时间以及每个方法执行时间 我可以通过调用自己的方法来做到这一点EventLogger LogMethodCall方法在每个方法的开头 但我想知道是否有办法使CLR每次
  • 使用预编译头减少 clang 编译时间

    我正在开发一个数据库项目 该项目将查询 以某种高级语言表示 编译为 C 代码 这段代码由数据库编译并执行 那部分工作得很好 现在 我正在尝试减少 C 查询代码的编译时间 我想知道是否可以使用预编译头来提高性能 该查询被转换为一个名为 Que
  • 在 DataGridView 中隐藏行非常慢

    我在 Winforms 应用程序中有一个 DataGridView 大约有 1000 行 未绑定 和 50 列 隐藏一列需要整整 2 秒 当我想隐藏大约一半的行时 这就成为一个问题 private void ShowRows string
  • 宏可以按参数数量重载吗?

    如何this https stackoverflow com q 9183993 153285工作 如何实现 C99 C 11 可变参数宏以仅根据为其提供多少个参数来扩展到不同的事物 编辑 请参阅末尾以获得现成的解决方案 要获得重载的宏 首
  • “包含字符串”的快速索引

    在我的应用程序中 我有多达数百万个短字符串 大部分短于 32 个字符 我想实现一个带有附加列表的搜索框 该列表仅包含包含在搜索框中输入的整个字符串的元素 如何预先建立索引来快速找到此类字符串 所有排序的 STL 容器都会检查整个字符串 对于
  • 使用 Matplotlib、PyQt 和 Threading 进行实时绘图导致 python 崩溃

    我一直在努力研究我的 Python 应用程序 但找不到任何答案 我有 PyQT GUI 应用程序 它使用 Matplotlib 小部件 GUI 启动一个新线程来处理 mpl 小部件的绘图 恐怕我现在通过从另一个线程访问 matplotlib
  • C++:初始化静态字符串成员

    我在 C 中初始化静态字符串成员时遇到一些问题 我有几个类 每个类都包含几个表示 id 的静态字符串成员 当我通过调用静态函数初始化变量时 一切都很好 但是 当我想为一个变量分配另一个变量的值时 它仍然保留空字符串 这段代码有什么问题 st
  • C for 循环索引:新 CPU 中的前向索引更快吗?

    在我订阅的邮件列表上 两位知识渊博的 IMO 程序员正在讨论一些优化的代码 并说了以下内容 在 5 8 年前发布的 CPU 上 向后迭代 for 循环稍微快一些 e g for int i x 1 i gt 0 i 因为比较i归零比将其与其
  • 函数参数评估顺序[重复]

    这个问题在这里已经有答案了 在 C 和 C 中 函数参数的求值是否有固定的顺序 我的意思是 标准怎么说 是吗left to right or right to left 我从书中得到的信息令人困惑 是否有必要function call应该使
  • 捕获另一个进程未处理的异常

    我想知道我是否可以捕获我开始使用 Process Start 的另一个进程抛出的未处理的异常 我知道我可以用这个捕获标准错误link http social msdn microsoft com Forums en US csharpgen
  • 如何强制用户仅使用“new”创建从我派生的类的对象?

    为了实现引用计数 我们使用IUnknown http msdn microsoft com en us library ms680509 VS 85 aspx类接口和智能指针模板类 该接口具有所有引用计数方法的实现 包括Release vo
  • 如何填充两个样条线或直线系列之间的区域

    我有这个Chart 如何填充两个之间的区域Series S0 and S1 说蓝色和黄色Series 为此 我们编写了其中之一Paint事件 这里的ValueToPixelPosition https msdn microsoft com
  • Visual Studio Code 调试默认 ASP.NET Core MVC WebApp:不起作用

    我正在使用 Manjaro linux 并尝试调试默认的 ASP NET Core MVC 项目 但调试停止 没有任何错误 我创建了该项目 dotnet new mvc in a Meow文件夹 没什么特别的 然后添加了新的配置 NET C
  • 只读有运行时开销吗?

    出于某种原因 我一直认为readonly字段有与其相关的开销 我认为这是 CLR 跟踪是否存在readonly字段是否已初始化 这里的开销是一些额外的内存使用量 用于跟踪状态以及分配值时的检查 也许我这么认为是因为我不知道readonly字
  • 如何解决内存碎片

    我们偶尔会遇到这样的问题 长时间运行的服务器进程 在 Windows Server 2003 上运行 由于内存分配失败而引发异常 我们怀疑这些分配由于内存碎片而失败 因此 我们一直在寻找一些可能对我们有帮助的替代内存分配机制 我希望有人能告
  • 非静态类中的静态方法和静态类中的静态方法有什么区别?

    我有两个班级A级和B级 static class ClassA static string SomeMethod return I am a Static Method class ClassB static string SomeMeth
  • 字符串 c 的二叉树

    我正在尝试实现一个能够在 c 中保存字符串的二叉树 在让代码适用于整数之后 我尝试稍微修改它以处理字符数组 现在我似乎完全破解了代码 但不知道如何破解 任何帮助表示赞赏 include
  • 为什么绿色线程不能在多核上工作

    在维基百科上 绿色线程 http en wikipedia org wiki Green threads被描述为通常无法在多核上运行 而没有解释原因 在多核处理器上 本机线程实现可以 自动将工作分配给多个处理器 而绿色线程 实现通常不能 我
  • 获取会议组织者邮件地址 EWS API

    我想使用 EWS API 获取会议组织者的邮件地址 目前 我刚刚获得约会项目的一些属性 我听说你可以设置你想要获取哪些属性 我的代码看起来像这样 CalendarView cview new CalendarView start end c

随机推荐

  • CSS 显示表格与普通 HTML 表格

    由于某种原因 我需要在我的 Web 应用程序中显示表格数据 但不使用本机 语义表 thead tbody th td 标签 我发现 CSS 属性使 html 元素 看起来 行为 像表格 http www quirksmode org css
  • RabbitMQ 队列可以有多个订阅者吗?

    我的 C 控制台应用程序中有以下超级代码 用于从 RabbitMQ 队列中排出消息 consumer new EventingBasicConsumer channel consumer Received o e gt onMessageR
  • FFmpeg - 连接视频错误,与相应的输出链接不匹配?

    我正在尝试使用 ffmpeg 将一些视频连接到一个视频中 输入信息 a mp4 1920x808 b mkv 1280x720 首先我尝试了下面的命令 它工作正常 ffmpeg i a mp4 i b mkv f lavfi t 0 1 i
  • 如何区分 Visual Studio 项目类型和现有 Visual Studio 项目

    使用 Visual Studio 2005 sln 或 vcproj 文件 或其他任何地方 中是否有任何定义项目类型 子类型的内容 编辑 我的意思是 当您创建项目时 首先选择一种语言 例如 Visual C 然后选择项目类型 例如 Wind
  • 使用 AJAX 和 JSONP 时未捕获的 SyntaxError 和 CORS 错误

    当我执行 AJAX 调用时 出现以下错误 未捕获的语法错误 意外的标记 但是 当我直接在浏览器中访问相同的 URL 时 我得到了预期的 JSON 响应 我做错了什么以及如何解决它 下面是我的 jQuery AJAX 请求 ajax type
  • LNK1104 无法打开文件“legacy_stdio_definitions.lib”

    我已将我的项目从 vs 2012 移植到 vs 2015 我正在使用的库也是从 vs 2015 构建的 我使用 makefile 构建项目并收到此错误 LNK1104 cannot open file legacy stdio defini
  • 如何在java swing应用程序中保留和删除多个图形对象?

    我有一个图像 我使用其上的预定义位置来创建带有颜色的图形对象 单击鼠标 我尝试在其上用颜色创建一些椭圆形 事实上我没能达到这个目的 因为 当我单击预定义位置时 我可以在其上创建一个椭圆形 但是当我单击另一个预定义位置时 第一个椭圆形消失了
  • 如何在 SQL Server 中将日期正确转换为 ISO-8601 周数格式?

    ISO 8601 规定周数的格式为YYYY W 请注意 周数应为两位数 如 01 02 SELECT cast DATEPART YYYY CreationDate as varchar W cast DATEPART ISO WEEK G
  • 使用 udev 更改 ttyUSB 权限

    我的程序需要访问ttyUSB没有root权限 我尝试用它来改变它chmod 777 dev ttyUSB0如您所知 当我重新启动时 此权限更改为默认值 我如何为此配置我的 udev Rules d 寻找ttyUSB in the rules
  • m2e无法从nexus传输元数据,但maven命令行可以

    我正在使用 nexus 来托管我的 Maven 存储库 并且 maven 命令行 win32 和 linux 可以使用相同的命令和相同的 settings xml 成功地从该 nexus 传输工件 但 m2e 会失败 如下所示 WARNIN
  • 表达式中上标和下标相同的字符

    在情节中 我想要一个标题 其中应该包含 字符串 my title is 后跟由 引发的 caharecter alpha 即 alpha prime alpha 也有下标 G I tried expression paste my titl
  • 通过Python使用refresh token完成Oauth2.0授权(Google API服务创建)

    我正在尝试使用 Oauth2 通过无头 Linux 服务器访问 Google API 服务 我通读了这篇文章的所有答案 如何在没有用户干预的情况下授权应用程序 网络或安装 但他们都没有展示如何使用刷新令牌来生成访问令牌python pinn
  • 雅虎财经API

    如何使用 YQL 获取雅虎财经股票代码的完整列表 不尝试获取单个股票报价 我正在尝试找到可用股票代码的完整列表 例如 所有股票代码均来自纽约证券交易所 纳斯达克 雅虎财经在这方面可能帮不了你太多 您可以从交易所获取所有股票代码 然后在雅虎财
  • 如何使用 PHP 来使用 JavaScript?

    设想 我使用创建了一个过滤IF ELSE当用户单击 BOX A 和 BOX B 然后假设 BOX A 已满 在用户点击 保存按钮 后 将显示一条确认消息 说明 您选择的盒子已经满了 您想保存其他物品吗 这是我的代码
  • 如何在 Powershell 中同时对多个服务器运行命令

    我正在寻找一种方法来同时重新启动多个服务器上的三个服务 我知道如何使用循环针对服务器列表重新启动服务 但由于我有许多服务器 因此需要很长时间才能等待每台服务器上的每个服务按顺序重新启动 有没有办法立即向所有服务器发送重新启动服务命令 而不是
  • Python:找出本地时区

    我想将日志文件中的 UTC 时间戳与本地时间戳进行比较 创建本地时datetime对象 我使用类似的东西 gt gt gt local time datetime datetime 2010 4 27 12 0 0 0 tzinfo pyt
  • 异步启动长时间运行的进程

    在我们的 Web 应用程序中 用户可以进行需要更新大量数据库表的更改 所有这些的加载时间最长可达 30 秒 我不希望用户在导航到另一个页面之前等待该操作完成 我已将长时间运行的代码放在自己的页面上 例如 updateinfo aspx 并尝
  • 在 .net 4.0 中使用实体框架与 Oracle 数据库 - 可能吗?

    我正在构建一个针对 Net 4 0 的应用程序 目前不能更高 我需要访问 Oracle Db 11g 并且我想使用实体框架 为了能够做到这一点 我知道我必须使用 Oracle 托管数据访问 Oracle ManagedDataAccess
  • “参数无效。”使用保存位图时

    我正在尝试以指定的编码质量保存位图 jpg 格式 但是 在调用保存方法时出现异常 参数无效 如果我省略 bmp save 中的最后两个参数 它就可以正常工作 EncoderParameters eps new EncoderParamete
  • 易失性、互锁性、锁定性

    假设一个类有一个public int counter由多个线程访问的字段 这int仅递增或递减 要增加此字段 应使用哪种方法 为什么 lock this locker this counter Interlocked Increment r