[英]Thread safe generic alternative to Interlocked.Exchange and Interlocked.Exchange global struct support
`Interlocked.MemoryBarrier' 是否为泛型类型支持提供了足够的防护,如以下示例中实现的那样?
// Out of scope Interlocked.* methods omitted
public static T CompareExchange<T>(ref T location, T value, T comparand)
where T : unmanaged
{
Interlocked.MemoryBarrier();
if (Unsafe.AreSame(ref location, ref comparand))
return Exchange(ref location, value);
return location;
}
public static T Exchange<T>(ref T location, T value)
where T : unmanaged
{
Interlocked.MemoryBarrier();
location = value;
Interlocked.MemoryBarrier();
return location;
}
在您的实现中,“Unsafe.AreSame”简单地检查对相同 memory 位置的引用。 它并没有像您的意图那样比较结构是否相等(否则只需将内置的泛型重载用于引用类型)。
关于 Interlocked.MemoryBarrier(),它不提供跨线程的排序保证 - 仅阻止某些指令优化。 在您的示例中,对 Exchange 的此实现的两个并发调用可能会返回相同的初始值,这是不正确的。
为了实现原子性,您限制为最大 8 字节的结构。 以下将在 8 字节约束下实现您的 object:
public static T CompareExchange<T>(ref T location, T value, T comparand)
where T : unmanaged =>
Unsafe.SizeOf<T>() switch
{
4 => Unsafe.As<int, T>(ref Unsafe.AsRef(Interlocked.CompareExchange(ref Unsafe.As<T, int>(ref location), Unsafe.As<T, int>(ref value), Unsafe.As<T, int>(ref comparand)))),
8 => Unsafe.As<long, T>(ref Unsafe.AsRef(Interlocked.CompareExchange(ref Unsafe.As<T, long>(ref location), Unsafe.As<T, long>(ref value), Unsafe.As<T, long>(ref comparand)))),
_ => throw new NotSupportedException("Type exceeds 8-bytes")
};
public static T Exchange<T>(ref T location, T value)
where T : unmanaged =>
Unsafe.SizeOf<T>() switch
{
4 => Unsafe.As<int, T>(ref Unsafe.AsRef(Interlocked.Exchange(ref Unsafe.As<T, int>(ref location), Unsafe.As<T, int>(ref value)))),
8 => Unsafe.As<long, T>(ref Unsafe.AsRef(Interlocked.Exchange(ref Unsafe.As<T, long>(ref location), Unsafe.As<T, long>(ref value)))),
_ => throw new NotSupportedException("Type exceeds 8-bytes")
};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.