我需要经常更新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
我有两个选择:
InstrumentInfo
仅创建一个Instrument
。某些字段更新时,例如BestBuy
只更新此字段的值。客户端应仅获得InstrumentInfo
一次,并在整个应用程序生命周期内使用它。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
是首选的?欢迎任何建议。
答案 0 :(得分:2)
使用
2
我根本不需要锁定,因为参考更新是原子的。但我可能会使用更多的内存,我可能会为GC创建更多的工作,因为
不,您的选项1
可能会导致更多的GC负载(通过向下一代推广更多对象)。
使用最明智,最易于维护的形式。在这种情况下,创建新对象。
不要根据您的想法进行优化可能会变慢。使用分析器。
答案 1 :(得分:2)
你应该考虑几个不相关的观点。
当你没有锁时,你应该没有它们,当然。当你选择多线程时,更喜欢不可变对象。
另一方面,不可变对象
你的第二种方法仍然需要一些并发处理策略,因为有几个线程可能set
使用不同的起始假设信息。
我不确定引用赋值是否为原子。如果是,为什么CLR有感谢Henk Holterman指出这一点。Interlocked.Exchange<T>
?