对.NET中未对齐字段的读写是绝对原子的吗?

时间:2013-03-06 14:15:17

标签: c# .net atomic memory-alignment

C#规范(ECMA-334ISO/IEC 23270)有一段关于读写的原子性:

  

12.5变量引用的原子性

     

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

但我很难想象永远是真的。例如,我可以使用StructLayout attribute布局结构,并强制字段不对齐:

// sizeof(MyStruct) == 9
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct MyStruct
{
    public byte pad;   // Offset: 0
    public int value1; // Offset: 1
    public int value2; // Offset: 5
}

现在当我这样做时,我认为对int的写入不是原子,因为它没有与自然边界对齐:

MyStruct myStruct = new MyStruct();
myStruct.value1 = 20;

那么,它是绝对原子的(就像规范所说的那样),还是不保证是原子的(例如在x86上)?无论哪种方式,你有任何消息来支持这个吗?

1 个答案:

答案 0 :(得分:6)

我认为你是对的...有些情况下,如果你故意不按自己的方式,系统将不会按照语言规范行事。重要的是,ECMA-335在分区I第12.6.6节中明确指出:

  

符合要求的CLI应保证对正确对齐的内存的读写访问权限   不大于本机字大小(native int类型的大小)的位置是原子的   (参见§I.12.6.2)当对一个位置的所有写访问都是相同的大小时。原子写入应   除了写的那些之外不要改变任何比特除非明确的布局控制(参见   分区II(控制实例布局))用于更改默认行为,数据元素号   大于自然字大小(原生int的大小)应正确对齐。宾语   引用应被视为存储在本机字大小中。

(大胆强调我的;斜体是在规范中。)