C# lock 语句中的 Nop 生成

Bac*_*ave 2 c# locking

我刚刚读了 Eric Lippert 的一篇文章http://ericlippert.com/2009/03/06/locks-and-exceptions-do-not-mix/

对于以下代码,他提到编译器可以在监视器输入和受保护区域之间生成无操作指令:

var temp = obj;
Monitor.Enter(temp);
try { body }
finally { Monitor.Exit(temp); }
Run Code Online (Sandbox Code Playgroud)

为什么编译器会在那里生成一个 nop?

Han*_*ant 5

这是传统 x64 抖动的问题。它使用 NOP 指令来对齐代码。对齐代码是一种优化策略,它使分支预测器更高效,并减少指令解码器为达到分支目标而必须做的工作。您可以在题为“英特尔 64 位和 IA-32 架构优化参考手册”章节 3.4.1.5 的英特尔处理器手册中看到这一点:

汇编/编译器编码规则 12.(M 影响,H 通用性)所有分支目标都应该是 16 字节对齐的。

遗憾的是,这些 NOP 现在可能是 Thread.Abort() 的目标,允许在到达 try/finally 块之前中止线程。令人不快的结果是锁定将被获取但不会被释放。发生这种情况的几率非常低,而不是零。

这不是完整的故事,afaik 这只是抖动中的一个简单错误,因为 try 块实际上不是分支目标。传统的 x64 抖动团队还有其他一些棘手的问题,看起来他们的成员在工作完成后分散了,并且已知的错误没有得到修复。微软创建了一个新团队,他们重写了抖动,项目名称 RyuJIT,从 .NET 4.6 开始可用。他们放弃了 x64 代码库,并使用 x86 抖动代码库作为起点。