Interlocked.Increment
相关方法依靠硬件指令对单个32bit或64bit内存值进行同步修改,保证访问同一个值的多个线程不会读/写陈旧数据。这是必要的,因为在硬件级别,处理器具有内存值的本地/总线副本(出于性能考虑,通常称为总线内存或 cpu 缓存)。
lock(){}
对一段代码执行同步,而不是单个整数值。而不是依靠硬件指令来同步对变量的访问,结果代码而是依靠操作系统同步原语(软件,而不是硬件)来保护内存和代码执行。
此外,lock() 的使用会发出内存屏障,确保从多个 CPU 访问相同的变量会产生同步(非陈旧)数据。这在其他语言/平台中并非如此,在这些语言/平台中,必须显式执行内存屏障和防护。
对整数值使用方法更有效,Interlocked
因为硬件具有执行必要同步的本机支持。但是这种硬件支持只存在于 __int32 和 __int64 等本机积分,因为硬件没有更高级别的复杂类型的概念,因此不会从Interlocked
类型中公开这种高级方法。因此,您不能使用Interlocked
同步分配System.String
或任何System.Object
派生类型。
(即使如果您使用较低级别的语言,可以使用相同的硬件指令来分配指向字符串值的指针,但事实是,在 .NET 中,字符串对象不表示为指针,因此它不是可以在任何“纯”.NET 语言中使用。我正在避免这样一个事实,即您可以使用不安全的方法来解析指针并在您真的想要的情况下对字符串值进行联锁分配,但我觉得这不是真的你在问什么,而且 Interlocked 不支持这一点,因为需要在引擎盖下进行 GC 固定,这可能会比使用更昂贵和更具侵入性lock()
。)
因此,对于“引用类型”的同步修改/分配,您将需要使用同步原语(即 lock(){}、Monitor 等)。如果您只需要同步一个整数值(Int32、Int64),那么使用 Interlocked 方法会更有效。如果有多个整数值要同步,则使用 lock() 语句可能仍然有意义,例如增加一个整数同时减少第二个整数,其中两者都需要作为单个逻辑操作进行同步。