使用CLR(和变体)将哪些CPU体系结构写入int"隐式易失性"?

 哈哈哈阿笑 发布于 2023-02-13 11:59

我最近在这里学到以下是x86 CPU上的线程安全x86 CLR(不一定是ECMA标准CLR)

public class SometimesThreadSafe
{
    private int value;
    public int Value { get { return value; } }

    public void Update()
    {
        Interlocked.Add(ref value, 47);
    }
}

这是因为写入int这样的体系结构可确保任何其他有价值的CPU缓存同步.但是在ARM CPU上,这不是线程安全的!从另一个线程读取值可以从CPU缓存中读取旧副本.

所以问题是什么CPU架构和什么版本的CLR及其变体,例如Mono,这个线程安全吗?

1 个回答
  • "线程安全"并不是适用于这种代码的正确词.对Value属性getter的访问与Update()方法完全不同步,因此您获得的值完全不可预测.包括从未见过更新.

    如果Value属性getter是原子的,那么你唯一关心的就是这里.换句话说,如果您能够观察到属性的部分更新值,其中某些字节将由Update()更改而某些字节不会更改.这是CLI规范保证的.Ecma-335,第I.12.6.6节,"原子读写":

    符合要求的CLI应保证当对位置的所有写访问都是原子时,对正确对齐的内存位置的读写访问不大于本机字大小(native int类型的大小)是原子的(参见§I.12.6.2).大小相同.原子写入除了写入之外不得改变任何位.除非使用显式布局控制(请参阅分区II(控制实例布局))来更改默认行为,否则应正确对齐不大于自然字大小(本机int的大小)的数据元素.对象引用应被视为存储在本机字大小中.

    在C#语言规范第5.5章"变量引用的原子性"中,这种保证有所降低.它避免依赖于IntPtr的大小:

    以下数据类型的读取和写入是原子的:bool,char,byte,sbyte,short,ushort,uint,int,float和reference类型.此外,在先前列表中具有基础类型的枚举类型的读取和写入也是原子的.其他类型的读写,包括long,ulong,double和decimal,以及用户定义的类型,不保证是原子的.

    Anyhoo,在任何架构上都不是int的问题.

    如果确实是线程安全问题,那么这段代码就是完全错误的.它在任何架构上都不是线程安全的..NET内存模型中不存在"隐式易变"的概念.x86 jitter优化器利用的东西,它会将属性的支持字段存储在cpu寄存器中,而不是从内存中更新它.你永远不会看到更新.需要明确声明它是不稳定的,以抑制此优化.

    2023-02-13 12:01 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有