如何使 T 类型的字段可变?

The*_*Saw 3 c# generics

我试图将一堆重复代码合并到一个具有以下结构的实用程序类中:

public class Shared<T>
{
    private volatile T _value;

    public object Lock { get; private set; }

    public T Value
    {
        get { lock (Lock) return _value; }
        set { lock (Lock) _value = value; }
    }

    public Shared(T startingValue)
    {
        _value = startingValue;
        Lock = new object();
    }

    public Shared()
        : this(default(T))
    {
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,C# 不会让我。文档指出T必须是引用类型或原语之一(int、bool 等)。我唯一关心的类型是引用类型和 bool。显然,我不能使用无界类型T。有没有办法让我完成这项工作?甚至可以为此添加约束以使其作为Shared<bool>? 我什至不允许将其他结构类型标记为 volatile。:(

如果没有可能的方法将其标记为 volatile,当多个线程试图读取此值时,我是否还有其他保证不会对其进行优化?

Phi*_*ght 5

您可以轻松地将泛型类型限制为仅引用...

public class Shared<T> where T : class
Run Code Online (Sandbox Code Playgroud)

...但也没有办法将其限制为布尔值。该类非常小,因此您只需为 Boolean 类型创建一个特定的实现即可。

但...

您在读取和写入值期间的锁定完全没有用。对象引用的读/写在 .NET 中是原子的,因此不需要锁定。它只会减慢速度。(布尔值实现为 4 字节整数,它们也是原子的,因此您的布尔版本也不需要它)

volatile 关键字意味着每次读取该值时,它将确保它再次从内存中读取该值。这解决了值可能缓存在寄存器或 L1/L2 缓存中的问题。在这种情况下,后续访问将是寄存器/缓存值,即使另一个 CPU 可能在主内存中更改了它。因此,您的 volatile 将防止将值缓存在寄存器中,并确保每次读取都与主内存一致。