如何正确读取Interlocked.Increment\'ed int字段?

如何解决如何正确读取Interlocked.Increment\'ed int字段?

| 假设我有一个非易失性int字段,以及一个
Interlocked.Increment
的线程。另一个线程可以安全地直接读取此内容,还是读取也需要互锁? 我以前认为我必须使用互锁读取来确保我看到的是当前值,因为毕竟该字段不是可变的。我一直用ѭ1来实现。 但是,我偶然发现了这个答案,这表明实际上纯读总是会看到version0值的当前版本,并且由于int读取已经是原子的,因此不需要做任何特殊的事情。我还找到了一个请求,Microsoft在其中拒绝了对Interlocked.Read(ref int)的请求,进一步表明这是完全多余的。 那么我真的可以安全地读取没有such4ѭ的
int
字段的最新值吗?     

解决方法

如果要保证另一个线程将读取最新值,则必须使用
Thread.VolatileRead()
。 (*) 读取操作本身是原子性的,因此不会造成任何问题,但是如果没有volatile读取,则可能会从缓存中获取旧值,或者编译器可能会优化代码并完全消除读取操作。从编译器的角度来看,代码在单线程环境中工作就足够了。易失性操作和内存障碍用于限制编译器优化和重新排序代码的能力。 有几个参与者可以更改代码:编译器,JIT编译器和CPU。哪一个表明您的代码已损坏并不重要。唯一重要的是.NET内存模型,因为它指定了所有参与者必须遵守的规则。 (*)
Thread.VolatileRead()
并未真正获得最新值。它将读取该值,并在读取后添加一个内存屏障。第一个易失性读取可能会获取缓存的值,而第二个易失性读取可能会获取更新的值,因为如果需要,第一个易失性读取的内存屏障已强制进行缓存更新。实际上,编写代码时,此细节并不重要。     ,有一点元问题,但是关于使用ѭ7的一个好方面(忽略了明显的缺点,即阅读时很难理解)是无论works3还是ѭ9都可以使用。的确,
int
读取始终是原子的,但是
long
读取不是或可能不是,这取决于体系结构。不幸的是,只有当
value
的类型为
long
时,
Interlocked.Read(ref value)
才有效。 考虑到您以
int
字段开头的情况,这使得不可能使用
Interlocked.Read()
,因此您将直接读取该值,因为无论如何这都是原子的。但是,在以后的开发中,您或其他人决定需要ѭ9-编译器不会警告您,但现在您可能会遇到一个细微的错误:不再保证读取访问权限是原子的。我发现在这里使用
Interlocked.CompareExchange()
是最好的选择。根据底层处理器指令,它可能会更慢,但从长远来看,它会更安全。我对ѭ5的内部知识还不够了解。关于此用例,它可能会“更好”,因为它提供了更多的签名。 我不会尝试在循环或任何紧的方法调用中直接读取值(即没有上述任何机制),因为即使写入是易失性和/或内存障碍,也没有什么告诉编译器该字段的值实际上可以在两次读取之间改变。因此,该字段应为
volatile
或应使用任何给定的构造。 我的两分钱。     ,您是正确的,您不需要特殊的指令即可自动读取32位整数,但是,这意味着您将获得\“ whole \”值(即,您不会获得部分写入和部分写入)另一个)。您无法保证一旦阅读该值就不会更改。 此时,您需要确定是否需要使用其他同步方法来控制访问,例如是否要使用此值从数组中读取成员,等等。 简而言之,原子性可确保操作完全且不可分割地进行。给定某些操作
A
包含
N
步骤,如果您在
A
之后立即执行该操作,则可以确保所有ѭ22happened步骤均与并发操作隔离发生。 如果您有两个线程执行了原子操作
A
,那么可以保证您只会看到两个线程之一的完整结果。如果要协调线程,则可以使用原子操作来创建所需的同步。但是原子操作本身并不能提供更高级别的同步。
Interlocked
系列方法可用于提供一些基本的原子操作。 同步是一种更广泛的并发控制,通常围绕原子操作构建。大多数处理器都包括内存屏障,可让您确保所有高速缓存行都被清空并且您拥有一致的内存视图。易失性读取是确保对给定存储位置进行一致访问的一种方法。 尽管不是立即适用于您的问题,但阅读有关数据库的ACID(原子性,一致性,隔离性和持久性)可能会帮助您使用术语。     ,是的,您阅读的所有内容都是正确的。 Interlocked.Increment的目的是使对字段进行更改时正常读取不会为假。读字段不是危险的,写字段是危险的。     

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 <select id="xxx"> SELECT di.id, di.name, di.work_type, di.updated... <where> <if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 <property name="dynamic.classpath" value="tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams['font.sans-serif'] = ['SimHei'] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -> systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping("/hires") public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate<String
使用vite构建项目报错 C:\Users\ychen\work>npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-