具有易失性或锁定的属性

2024-01-04

我有一个带有支持字段的属性,我想使其线程安全(获取和设置)。 get和set方法除了设置和返回之外没有任何逻辑。

我认为有两种方法可以将逻辑封装在属性 self 中(易失性和锁定)。 我对两者的理解是正确的还是有错误?

以下是我的例子:

    public class ThreadSafeClass
    {
        // 1. Volatile Example:

        private volatile int _processState_1;
        public int ProcessState_1
        {
            get { return _processState_1; }
            set { _processState_1 = value; }
        }

        // 2. Locking Example:

        private readonly object _processState_2Lock = new object();
        private int _processState_2;
        public int ProcessState_2
        {
            get
            {
                lock (_processState_2Lock)
                {
                    return _processState_2;
                }
            }
            set
            {
                lock (_processState_2Lock)
                {
                    _processState_2 = value;
                }
            }
        }
    }

欲了解更多信息,请参阅J. Albahari 的很棒的网站 http://www.albahari.com/threading/part4.aspx#_The_volatile_keyword:

同步结构可以分为四类:

简单的拦截方法:

它们等待另一个线程完成或经过一段时间。Sleep, Join, and Task.Wait是简单的阻塞方法。

锁定结构:

这些限制了一次可以执行某些活动或执行一段代码的线程数量。独占锁定结构是最常见的——它们一次只允许一个线程进入,并允许竞争线程访问公共数据而不会互相干扰。标准的独占锁定结构是lock (Monitor.Enter/Monitor.Exit), Mutex, and SpinLock。非排他性的locking构造是Semaphore, SemaphoreSlim,以及reader/writer locks.

信号传导结构:

这些允许线程暂停,直到收到另一个线程的通知,从而避免低效的轮询。有两种常用的信号设备:事件等待句柄和监视器的等待/脉冲方法。框架4.0引入了CountdownEvent and Barrier类。

非阻塞同步构造:

它们通过调用处理器原语来保护对公共字段的访问。 CLR 和 C# 提供以下非阻塞构造:Thread.MemoryBarrier, Thread.VolatileRead, Thread.VolatileWrite, the volatile关键字,以及Interlocked class.


The volatile关键词:

volatile 关键字指示编译器在每次读取该字段时生成一个获取栅栏,并在每次写入该字段时生成一个释放栅栏。获取栅栏可防止其他读/写在栅栏之前移动;释放栅栏可防止其他读/写在栅栏之后移动。这些“半栅栏”比全栅栏更快,因为它们为运行时和硬件提供了更多优化空间。

碰巧的是,Intel 的 X86 和 X64 处理器总是对读取应用获取栅栏,对写入应用释放栅栏 — 无论您是否使用 volatile 关键字 — 因此,如果您使用这些处理器,则该关键字对硬件没有影响。然而,volatile确实会对编译器和 CLR 以及 64 位 AMD 和(在更大程度上)安腾处理器执行的优化产生影响。这意味着您不能因为您的客户端运行特定类型的 CPU 而更加放松。

将 volatile 应用于字段的效果可以总结如下:

First instruction   Second instruction  Can they be swapped?
Read                Read                No
Read                Write               No
Write               Write               No (The CLR ensures that write-write operations are never swapped, even without the volatile keyword)
Write               Read                Yes!

请注意,应用 volatile 并不会阻止先写后读的交换,这可能会造成脑筋急转弯。 Joe Duffy 用下面的例子很好地说明了这个问题:如果Test1 and Test2在不同的线程上同时运行,a 和 b 的值有可能都为 0(尽管两者都使用了 volatile)x and y):

class IfYouThinkYouUnderstandVolatile
{
  volatile int x, y;

  void Test1()        // Executed on one thread
  {
    x = 1;            // Volatile write (release-fence)
    int a = y;        // Volatile read (acquire-fence)
    ...
  }

  void Test2()        // Executed on another thread
  {
    y = 1;            // Volatile write (release-fence)
    int b = x;        // Volatile read (acquire-fence)
    ...
  }
}

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

这为避免 volatile 提供了强有力的理由:即使您理解此示例中的微妙之处,其他处理您代码的开发人员也会理解它吗?两个作业之间的完整栅栏Test1 and Test2(或锁)解决了问题。

The volatile关键字不支持传递引用参数或捕获的局部变量:在这些情况下,您必须使用VolatileRead and VolatileWrite方法。

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

具有易失性或锁定的属性 的相关文章

  • 使用预编译头减少 clang 编译时间

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

    如何this https stackoverflow com q 9183993 153285工作 如何实现 C99 C 11 可变参数宏以仅根据为其提供多少个参数来扩展到不同的事物 编辑 请参阅末尾以获得现成的解决方案 要获得重载的宏 首
  • 无缝滚动瓷砖地图

    我正在开发一个自上而下的角色扮演游戏 并且想要实现无缝滚动地图 也就是说 当玩家探索世界时 地图之间没有加载屏幕 也没有通往下一个区域的 门 我有两种方法可以打破世界 在顶层 我有 区域 它只是 9 个 地图 的集合 这些区域仅由目录表示
  • 有没有办法将 boost::json::serializer 切换为美化输出?

    Using boost json serializer如中的示例所示文档 快速查看 http vinniefalco github io doc json json usage quick look html以紧凑格式保存 json tre
  • 读取STM32 MCU SPI数据寄存器的值

    有很多类似的问题 但似乎没有一个问题完全相同 我正在将 STML4 MCU 连接到 6 轴传感器 LSM6DS3 我已经成功地在 I2C 中实现了所有内容 但想要 SPI 的额外速度 和 DMA 如果我能让这些第一步工作起来的话 因此 第一
  • 命名空间“Microsoft”中不存在类型或命名空间名称“Practices”

    我正在使用 Microsoft Visual Studio 2005 for c 我的代码中有以下命名空间 using Microsoft Practices EnterpriseLibrary using Microsoft Practi
  • C for 循环索引:新 CPU 中的前向索引更快吗?

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

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 随着我的项目越来越多 我发现我经常从一个项目到另一个项目 从一个客户到另一个客户重复许多常见的任务 因此 我开始组装一个 实用程序 库 这是这些
  • ASP.NET MVC 路由 - 向路由添加 .html 扩展名

    我对 MVC 和路由非常陌生 我被要求修改一个应用程序以使用不同的 url 由于我没有经验 这项任务对我来说有点困难 好吧 让我们谈谈一些代码 routes MapRoute CategoryBySeName Route name prod
  • C++ 错误:从“char”到“const char*”的转换无效

    我对 C 完全陌生 我创建了这个函数 bool guessWord string compWord cout lt lt Guess a letter string userLetter cin gt gt userLetter for u
  • 使用 QGraphicsScene 实现流畅的动画

    我希望我的问题并不总是同样的问题 我有一个 QGraphicsScene 它的项目是一些 QGraphicsPixmap 我用一个计时器来移动它们 每秒 SetX 10 我设置 10是因为窗口大100 使用这个解决方案我的动画不流畅 我想我
  • 将一个整数从 C 客户端发送到 Java 服务器

    我使用此代码将一个整数从我的 Java 客户端发送到我的 Java 服务器 int n rand nextInt 50 1 DataOutputStream dos new DataOutputStream socket getOutput
  • 如何解决内存碎片

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

    我有两个班级A级和B级 static class ClassA static string SomeMethod return I am a Static Method class ClassB static string SomeMeth
  • 从 exit() 和 fork() 返回的结果奇怪地发生了位移

    我有一个 C 代码 有时会自行分叉 每个分叉都会执行一些操作 然后返回一个错误代码 目前 每个子进程返回其 ID 0 n void other int numero exit numero int main for int i 0 i lt
  • C# Julian 日期解析器

    我在电子表格中有一个单元格 它是 Excel 中的日期对象 但当它来自 C1 的 xls 类时 它会变成双精度型 类似于 2009 年 1 月 7 日的 39820 0 我读到这是儒略日期格式 有人可以告诉我如何在 C 中将其解析回 Dat
  • 未找到 _sqlite3_open 等符号错误

    您好 我收到此错误 Undefined symbols sqlite3 open referenced from main in ccRlWVer o sqliite3 close referenced from main in ccRlW
  • 获取会议组织者邮件地址 EWS API

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

    大多数时候 我都是这样做的 class a public a i 100 OK delete int j Compiler happy But is it safe The following code will lead compilat
  • 如何在没有 Visual Studio 的情况下将新文件添加到 .csproj 文件

    如何添加新文件到 csproj从命令提示符 我认为没有任何工具可以响应命令行上的 add project 命令来执行此操作 但我认为您可以幸运地创建一个程序 脚本来直接操作 csproj 文件的 XML 内容 csproj 文件的结构如下所

随机推荐

  • 添加第二个主节点以实现 kubernetes 中的高可用性

    我能够按照文档操作并建立一个 kubernetes 集群 但我想添加第二个主节点我在第二个节点上尝试了此操作但看到错误 root kubemaster02 kubeadm init apiserver advertise address 1
  • 如何在 Firefox 中使用“Start”和“End”在 Iframe 中选择一个范围,例如输入元素中的“selectionStart”

    对于 Internet Explorer 我有当前的代码来选择 iframe 中的范围 并将 desingMode 设置为 on var Range window document selection createRange var obj
  • 以编程方式重新加载 Java JAR,无需重新启动 ColdFusion

    背景 从 ColdFusion 10 开始 可以包含来自自定义位置的 JAR http help adobe com en US ColdFusion 10 0 Developing WSe61e35da8d318518 106e125d1
  • PHP中如何判断一个字符串是否是一个数学语句?

    我有这个字符串作为例子 2 2 2 当评估时它应该返回int 2 我正在寻找一个函数 解析器 可以确定字符串中是否匹配任何类型的数学内容 更多示例 2 2 2 4 8 12 128 8 不需要评估和计算这些数学表达式 只需要一个函数来确定
  • 如何获取 Titan 中的索引键列表?

    我正在使用 Titan v0 3 1 并且希望查看我已经通过索引建立索引的键的列表createKeyIndex 我怎样才能做到这一点 在 Gremlin shell 中 您可以使用蓝图键可索引图 https github com tinke
  • Docker 中的 Apache / PHP error_log 位置

    我的 PHP 脚本有错误 例如 屏幕上显示 警告 require var www foo php 无法打开流 我在日志中哪里可以找到这个 I tried docker logs containerName 但它只显示访问日志 例如 192
  • SQLAlchemy 和多进程的连接问题

    我在一个项目中使用 PostgreSQL 和 SQLAlchemy 该项目由启动子进程的主进程组成 所有这些进程都通过 SQLAlchemy 访问数据库 我遇到可重复的连接失败 前几个子进程工作正常 但一段时间后会出现连接错误 这是一个 M
  • 检查安装的网络打印机是否在线

    我想检查打印机是否在线 为此我得到了 OpenPrinter 的打印机句柄 然后我想使用 PRINTER STATUS OFFLINE 在 PRINTER INFO 6 中使用 GetPrinter 结果总是0 如何获取打印机的离线状态 我
  • 向条形图添加水平线

    我正在尝试使用R plotly s bar输入plot 来生成一个带有水平布局的框的图 并在其背景中添加一条水平线 而不是在它们的顶部 另外 我希望这条线在每个方向上对称地延伸一个盒子单元 这就是我正在做的 plot df lt data
  • android 在模拟器或设备中执行?

    有什么方法可以知道我的应用程序是在模拟器上还是在设备上运行 我使用的代码片段适用于 Intel 和 ARM 模拟器 if Build MODEL contains google sdk Build MODEL contains Emulat
  • `npmaudit` 不断返回“您配置的注册表 (https://registry.npmjs.org/) 不支持审核请求。”。我怎样才能让它再次工作?

    这是我得到的错误 npm ERR code ENOAUDIT npm ERR audit Your configured registry https registry npmjs org does not support audit re
  • 带有 @init 块的 ANTLR4 词法分析器规则

    我在 ANTLR v3 语法文件中定义了这个词法分析器规则 它的数学文本用双引号引起来 我需要将其转换为 ANTLR v4 ANTLR 编译器抛出错误 语法错误 在匹配词法分析器规则时不匹配输入 期望冒号 在 init 行中 词法分析器规则
  • 使用 C# 无法正确更改应用程序图标

    我将应用程序的图标更改为新图标 方法是转到 Project MyProject Properties Icon and Maniferest 然后加载新图标 现在 在我的调试文件夹中 我的 exe 文件的图标出现了新图标 这没关系 但是当我
  • Google App Engine 删除了默认 GCS 存储桶。有办法恢复吗?

    我正在从应用程序的默认存储桶中删除一些文件 并且不小心还使用 gsutil rm 命令删除了存储桶本身 有没有办法恢复 重新创建 恢复它 我想继续使用免费配额而不启用计费 到目前为止我试图做的是 但我不确定它是否正确 我首先启用计费只是为了
  • HTML 表格忽略元素样式宽度

    HTML 表格忽略元素样式宽度 我有一个 HTML 表格 其中某些单元格具有很长的文本内容 我想使用 jQuery 为这些单元格指定宽度 以像素为单位 但渲染的表格只是忽略给定的宽度 有什么方法可以强制表格遵守这个宽度吗 Thanks JS
  • 测量 OpenCV FPS

    我正在寻找一种正确的方法来测量 openCV FPS 我找到了几种方法来做到这一点 但它们都不适合我 我测试过的第一个使用time t 开始和 time t 结束 我认为一旦它返回一个转储的函数作为 fps x 时间图 我真的无法想象 fp
  • 将行号添加到现有 HTML

    我正在尝试向现有的 html 添加行号 行高不等 许多类型的字体大小和图像 每条线看起来像 div div
  • 如何使用适用于 Node.js 的 AWS 开发工具包在 s3 上创建文件夹或密钥?

    我正在使用适用于 Node js 的 AWS 开发工具包在 s3 上创建文件夹或密钥 我在谷歌上搜索 但一无所获 有谁知道如何使用适用于 Node js 的 AWS SDK 在我的存储桶下创建文件夹 如何检查您的存储桶中是否已存在该文件夹
  • 实体组件系统和共享公共基础类型的多个组件

    我正在尝试为我的游戏引擎实现一个简单的 ECS 我知道我的实现并不是严格意义上的 ECS 但我正在重构我的代码以使其更加基于组件 到目前为止 我有以下课程 Entity 它是组件的容器 并且由于我希望我的实体具有相同类型的多个组件 因此它将
  • 具有易失性或锁定的属性

    我有一个带有支持字段的属性 我想使其线程安全 获取和设置 get和set方法除了设置和返回之外没有任何逻辑 我认为有两种方法可以将逻辑封装在属性 self 中 易失性和锁定 我对两者的理解是正确的还是有错误 以下是我的例子 public c