我需要經常更新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
更新不能保證是原子。但我不需要重新定義對象。
With 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
是首選嗎?歡迎任何建議。
只是爲了防止*鎖定,鎖定「私有靜態只讀對象」而不是您的儀器信息陣列 - 就像防禦性編碼練習一樣。 – Adam 2012-08-14 09:13:14
@codesparkle - 鎖定一個'static'對象會導致(多)更多的爭用。目前的方法('ii'不是陣列)看起來不錯。 – 2012-08-14 09:15:42
@HenkHolterman他鎖定了'lock(instrumentInfos){'這是一個數組。 'ii'與它無關。但是你是對的,把它變成靜態是沒有必要的。只讀會做。 – Adam 2012-08-14 09:17:07