0

我需要InstrumentInfo经常更新课程。我从一个线程更新这个类并从另一个线程访问(读取)。

我有Instrument课。Instrument对于我需要维护的每个课程InstrumentInfo

// omit class Instrument as not improtant

public class InstrumentInfo
{
    public string Name { get; set; }
    public TradingStatus Status { get; set; }
    public decimal MinStep;
    public double ValToday;
    public decimal BestBuy;
    public decimal BestSell;
}

public class DerivativeInfo : InstrumentInfo
{
    public DateTime LastTradeDate { get; set; }
    public DateTime ExpirationDate { get; set; }
    public string UnderlyingTicker { get; set; }
}

// i do have several more subclasses

我确实有两个选择:

  1. InstrumentInfo每个只创建一个Instrument。当某些字段更新时,例如BestBuy只更新该字段的值。客户端应该InstrumentInfo只获取一次并在整个应用程序生命周期内使用它。
  2. 在每次更新时创建InstrumentInfo. 客户每次都应获取 InstrumentInfo 的最新副本。

1我确实需要锁定,因为不能decimal DateTime string保证更新是原子的。但我不需要恢复对象。

2我根本不需要锁定,因为更新reference是原子的。但我可能会使用更多内存,并且我可能会为 GC 创建更多工作,因为每次我需要实例化新对象(并初始化所有字段)。

1执行

    private InstrumentInfo[] instrumentInfos = new InstrumentInfo[Constants.MAX_INSTRUMENTS_NUMBER_IN_SYSTEM];

    // invoked from different threads
    public InstrumentInfo GetInstrumentInfo(Instrument instrument)
    {
        lock (instrumentInfos) {
            var result = instrumentInfos[instrument.Id];
            if (result == null) {
                result = new InstrumentInfo();
                instrumentInfos[instrument.Id] = result;
            }
            return result;
        }
    }

    ...........
    InstrumentInfo ii = GetInstrumentInfo(instrument);
    lock (ii) {
        ii.BestSell = BestSell;
    }

2执行:

    private InstrumentInfo[] instrumentInfos = new InstrumentInfo[Constants.MAX_INSTRUMENTS_NUMBER_IN_SYSTEM];

    // get and set are invoked from different threads
    // but i don't need to lock at all!!! as reference update is atomic
    public void SetInstrumentInfo(Instrument instrument, InstrumentInfo info)
    {
        if (instrument == null || info == null)
        {
            return;
        }
        instrumentInfos[instrument.Id] = info;
    }

    // get and set are invoked from different threads
    public InstrumentInfo GetInstrumentInfo(Instrument instrument)
    {
        return instrumentInfos[instrument.Id];
    }
    ....
    InstrumentInfo ii = new InstrumentInfo {
        Name = ..
        TradingStatus = ...
        ...
        BestSell = 
    }

    SetInstrumentInfo(instrument, ii); // replace InstrumentInfo

所以你怎么看?我想使用方法2,因为我喜欢没有锁的代码!lock我是否正确,因为我只是替换参考,所以我根本不需要?你同意这2是首选吗?欢迎任何建议。

4

2 回答 2

2

2我根本不需要锁定,因为参考更新是原子的。但我可能会使用更多内存,我可能会为 GC 创建更多工作,因为

不,您的选择1很可能会导致 GC 上的更多负载(通过将更多对象提升到下一代)。

  1. 使用最明智、可维护的形式。在这种情况下,创建新对象。

  2. 不要根据您的“认为”可能会更慢进行优化。使用分析器。

于 2012-08-14T09:09:59.490 回答
2

您应该考虑几个不相关的点。

  1. 当你可以不用锁时,你当然应该不用它们。当你选择多线程时,更喜欢不可变对象。

  2. 另一方面,不可变对象

    • 应变记忆
    • 被认为是“反OOP”
    • 客户端代码可能会错误地使用它们(因为人们不习惯使用它们)
  3. 您的第二种方法仍然需要一些并发处理策略,因为几个线程可能set具有不同的起始假设。

  4. 我不确定引用分配是原子的。如果是,为什么 CLR 有Interlocked.Exchange<T>感谢 Henk Holterman 指出这一点。

于 2012-08-14T09:17:03.230 回答