给定替身可以';不能用于挥发性领域,这是一种安全的替代方案吗

本文关键字:一种 安全 方案 替身 挥发性 用于 不能 | 更新日期: 2023-09-27 18:29:55

鉴于doubles不能在volatile字段中使用,这是一个安全的替代方案吗?或者它会导致一个空指针异常。

public sealed class DoubleStorage
{
    public readonly double Value;
    public DoubleStorage(double value)
    {
        this.Value = value;
    }
    public static readonly DoubleStorage Zero = new DoubleStorage(0);
}
public sealed class Val
{
    private volatile DoubleStorage boostResult = DoubleStorage.Zero;
    public double ThreadSafeDouble
    {
        set
        {
            //is this assignment attomic?
            boostResult = new DoubleStorage(value);
        }
        get
        {
            //or could this give null pointer exception?
            return boostResult.Value;
        }
    }
}

给定替身可以';不能用于挥发性领域,这是一种安全的替代方案吗

是的,访问引用是原子的。

然而,您可以将double框起来,不必创建一个类来封装它:

public sealed class Val {
  private volatile object boostResult = 0.0;
  public double ThreadSafeDouble {
    set {
        boostResult = value;
    }
    get {
        return (double)boostResult;
    }
  }
}

为变量指定一个double将创建一个对象,该对象将double框起来,然后为变量指定引用。由于引用赋值是原子的,所以它是线程安全的。

当取消装箱double时,从变量中读取引用是原子的,因此即使读取double不是原子的,也是线程安全的。由于带框的double是不可变的,因此特定的带框值永远不会更改。


或者通用版本:

public sealed class ThreadSafe<T> where T : struct {
  private volatile object _value;
  public ThreadSafe() {
    Value = default(T);
  }
  public ThreadSafe(T value) {
    Value = value;
  }
  public T Value {
    get {
      return (T)_value;
    }
    set {
      _value = value;
    }
  }
}
是的,这个解决方案是安全的,因为引用读写是原子的。