Как я могу сделать глобальный поток кеша безопасным
Раньше мое приложение было монопоточным, но теперь для повышения производительности нам нужно сделать его многопоточным.
У нас есть списки и элементы списка в следующей архитектуре:
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 ответ
Вам нужно выполнить некоторую синхронизацию при чтении. Вы не можете позволить одному потоку изменять структуру данных, в то время как другой пытается прочитать ее. Обычный подход - один писатель, блокировка нескольких читателей.
Delphi поставляется с одним из них, а именно TMultiReadExclusiveWriteSynchronizer
, Тем не менее, я считаю, что его производительность оставляет желать лучшего, и поскольку TMonitor
Я лично мало верю в способность инженеров Emba писать правильные примитивы синхронизации.
Я рекомендую использовать Slim Reader/Writer (SRW) Lock, представленный в Vista. Если вам все еще нужна поддержка XP, я бы предложил вернуться к критическому разделу.