c#不变性创建全球商店

时间:2018-08-16 23:13:31

标签: c# c#-7.0

对于我的项目,我正在尝试创建一个单一的全局存储以服务于这样的可变状态:

  // Immutable program state
  sealed public class State : IEquatable<State> {
    public State(ClientsConnections clientsConnections, ImmutableList<string> ids) {
      this.ClientsConnections = clientsConnections;
      this.Ids = ids;
    }

    public readonly ClientsConnections ClientsConnections; // ClientsConnections is immutable
    public readonly ImmutableList<string> Ids; // also immutable

    public override int GetHashCode() => HashCode.Combine(AgentsConnections.GetHashCode(), Ids.GetHashCode());
    public override bool Equals(object obj) { var o = obj as State; return o is null ? false : ClientsConnections.Equals(o.ClientsConnections) && Ids.Equals(Ids); }
    public bool Equals(State o) => object.Equals(this, o); 
    public static bool operator ==(State o1, State o2) => object.Equals(o1, o2); 
    public static bool operator !=(State o1, State o2) => !object.Equals(o1, o2);
  }

  // Store is a mutable singleton
  sealed public class Store {
    readonly object stateLock = new object();

    public Store() => this.State = new State(new ClientsConnections(), ImmutableList<string>.Empty);

    public State State { get; private set; }
    public void SetState(Func<State, State> f) { lock (stateLock) State = f(State); }
  }

然后我在如下代码中使用它:

Thread1 - f1() { 
  var currState=Store.State; 
  log(currState.ids);
}

Thread2 - f2() { 
  Store.SetState(currState => {
    var newids = currState.Ids.Add("hello");
    return new State(currState.ClientsConnections, newids);
  });
}

问题:

  1. 此代码线程安全吗?特别是我需要锁定Store.State getter吗?我的理由是,由于getter进行了原子分配,即按值复制状态引用,所以我不需要在这里锁定它?

  2. 我可以在这里使用ImmutableInterlocked吗?

1 个答案:

答案 0 :(得分:0)

  

此代码线程安全吗?特别是我需要锁定   Store.State吸气剂?我的推理是因为吸气剂具有原子性   赋值通过值复制状态引用,那么我不需要   锁在这里吗?

只要您对过时的数据感到满意,是的,它会很好地工作。

  

我可以在这里使用ImmutableInterlocked吗?

是的,我认为您应该这样做(但是您应该进行概要分析,以确认它是否确实带来了好处)。 ImmutableInterlocked.Update是我的建议。