MSIL操作码是原子的吗?

Kar*_*gha 9 .net multithreading cil atomic

我正在玩MSIL反编译器 - ILDASM,我试图反编译一个简单的.NET方法.

操作码看起来像这样:

.method private hidebysig static int32  Add(int32 a,
                                            int32 b) cil managed
{
  // Code size       18 (0x12)
  .maxstack  2
  .locals init ([0] int32 c,
           [1] int32 d,
           [2] int32 CS$1$0000)
  IL_0000:  nop
  IL_0001:  ldarg.0
  IL_0002:  ldc.i4.5
  IL_0003:  add
  IL_0004:  stloc.0
  IL_0005:  ldarg.1
  IL_0006:  ldc.i4.s   10
  IL_0008:  add
  IL_0009:  stloc.1
  IL_000a:  ldloc.0
  IL_000b:  ldloc.1
  IL_000c:  add
  IL_000d:  stloc.2
  IL_000e:  br.s       IL_0010
  IL_0010:  ldloc.2
  IL_0011:  ret
}
Run Code Online (Sandbox Code Playgroud)

我想知道的是 - 这些操作码是原子的吗?即在抢占式调度内核中,单个操作码在完成执行之前是否有可能被抢占?这里的操作码可以很容易地以1:1的方式映射到asm指令,因为它们具有用于加载,存储,添加等的单独操作码.

但是在更复杂的操作码的情况下呢?比如"call",当操作数是一个方法引用标记时,应首先遵循该方法来解析该方法然后调用?是原子吗?

Jon*_*eet 14

不,并非所有操作码都是原子的.例如,如果您使用stlocldloc大于本机指针大小的值类型,则不保证是原子的.

ECMA 335的第12.6.6节保证了这么多:

符合要求的CLI应保证当对位置的所有写访问都相同时,对正确对齐的内存位置的读写访问权限不大于本机字大小(native int类型的大小)是原子的(参见§12.6.2)尺寸.原子写入除了写入之外不得改变任何位.

......但是有一个说明:

[注意:当native int的大小为32位时,没有保证对8字节数据的原子访问,即使某些实现在数据在8字节边界上对齐时可能执行原子操作.结束说明]

这意味着任何存储或读取的操作代码Int64都不能保证在x86上是原子的,例如......

  • 是.挥发也没有帮助.(它很有帮助) (2认同)
  • @KarimA.:*如果*它正确对齐.我相信它会默认...... (2认同)