我怎样才能使全局缓存线程安全

时间:2013-02-20 13:25:20

标签: multithreading delphi thread-safety delphi-6 overhead-minimization

我的应用程序曾经是单线程,但现在为了提高性能,我们需要使它成为多线程。

我们在以下架构中有Lists和ListItem:

TBListItem = class(TBusinessObjects)
private 
  FList : TBList;
protected
  //methods
public 
  constructor Create(AList: TBList); reintroduce;
  //other methods
  //properties... 
end;

我们更喜欢列表的组成,而不是继承。

TBList = class(TPersistent)
private 
  FItemClass : TBListItemClass; //class of TBListItem

  //this is used to AddObject(key, object) of the TStringList duplicates are no allowed   
  function  BuildKey(ArrayOfKeys: array of Variant): string;
protected
  //we use a stringlist to save the items
  FList: TStringList; 

  function  GetItem(Index: Integer): TBListItem;
  //methods like Load(); Unload(); Save();
public 
  constructor Create(ARefClassItem: TBListItemClass); reintroduce;

  //these methods use buildkey
  function Add(ArrayOfKeys: Array of Variant): TBListItem; reintroduce;
  function FindByKey(const ArrayOfKeys: array of Variant): TBListItem;

  //other methods
  //properties... 
end;

在ADD()方法中执行以下操作:

var Index: Integer;
begin   
  Index:= FList.IndexOf(BuildKey(ArrayOfKeys));    
  if Index <> -1 then
    Result:= TBListItem(FList.Objects[Index])
  else 
  begin        
    Result:= FListItemClass.Create(Self);
    Result.FCodigo:= ArrayOfKeys;
    //load data from database.
    FList.AddObject(BuildKey(ArrayOfKeys), Result)
  end;    
end;

正如我所说,这些对象用于在运行时记录缓存数据,但每当我们需要读取/写入对象时,我们必须:

EnterCriticalSection(instance of TRTLCriticalSection);
//Do Stuff
LeaveCriticalSection(Same instance);

我无法改变很多建筑,因为有许多类继承了这一点 当我运行这些流程时,处理器图形中会出现很多尖峰,并且还会有很多停机时间 系统是从delphi 6编译器编译的 临界会话已在单元初始化中创建。

还有其他办法吗?
我可能至少不会锁定读数吗?

另外,我必须保证完整性,不允许使用相同键的2个对象。

1 个答案:

答案 0 :(得分:3)

您需要在阅读时执行一些同步。你不能让一个线程改变数据结构,而另一个线程试图读取它。一种常见的方法是单个编写器,多个读卡器锁。

Delphi附带其中一个,即TMultiReadExclusiveWriteSynchronizer。但是,我认为它的性能很差,而且由于TMonitor崩溃,我个人对Emba的工程师编写正确的同步原语的能力缺乏信心。

我的建议是使用Vista中引入的Slim Reader/Writer (SRW) Lock。如果你仍然需要支持XP,那么我建议你回到关键部分。