Хотя это не так просто, как c #, вам могут помочь следующие.
with Lock(mySharedObj) do
begin
//...do something with mySharedObj
UnLock;
end;
В двух словах
- список хранится для каждого экземпляра , который вы хотите защитить.
- когда второй поток вызывает
Lock(mySharedObj)
, во внутреннем списке будет выполнен поиск существующей блокировки. Новая блокировка будет создана, если существующая блокировка не найдена. Новый поток будет заблокирован, если другой поток все еще имеет блокировку.
-
Unlock
необходим, потому что мы не можем быть уверены, что ссылка только на экземпляр ILock выйдет из области действия в конце метода, вызывающего Lock
. (Если бы мы могли, Unlock
можно было бы удалить).
Обратите внимание, что в этом проекте создается один TLock для каждого экземпляра объекта, который вы хотите защитить, без его освобождения до тех пор, пока приложение не завершится.
Это может быть учтено, но это будет связано с возня с _AddRef & _Release.
unit uLock;
interface
type
ILock = interface
['{55C05EA7-D22E-49CF-A337-9F989006D630}']
procedure UnLock;
end;
function Lock(const ASharedObj: TObject): ILock;
implementation
uses
syncobjs, classes;
type
_ILock = interface
['{BAC7CDD2-0660-4375-B673-ECFA2BA0B888}']
function SharedObj: TObject;
procedure Lock;
end;
TLock = class(TInterfacedObject, ILock, _ILock)
private
FCriticalSection: TCriticalSection;
FSharedObj: TObject;
function SharedObj: TObject;
public
constructor Create(const ASharedObj: TObject);
destructor Destroy; override;
procedure Lock;
procedure UnLock;
end;
var
Locks: IInterfaceList;
InternalLock: TCriticalSection;
function Lock(const ASharedObj: TObject): ILock;
var
I: Integer;
begin
InternalLock.Acquire;
try
//***** Does a lock exists for given Shared object
for I := 0 to Pred(Locks.Count) do
if (Locks[I] as _ILock).SharedObj = ASharedObj then
begin
Result := ILock(Locks[I]);
Break;
end;
//***** Create and add a new lock for the shared object
if not Assigned(Result) then
begin
Result := TLock.Create(ASharedObj);
Locks.Add(Result);
end;
finally
InternalLock.Release;
end;
(Result as _ILock).Lock;
end;
{ TLock }
constructor TLock.Create(const ASharedObj: TObject);
begin
inherited Create;
FSharedObj := ASharedObj;
FCriticalSection := TCriticalSection.Create;
end;
destructor TLock.Destroy;
begin
FCriticalSection.Free;
inherited Destroy;
end;
procedure TLock.Lock;
begin
FCriticalSection.Acquire;
end;
function TLock.SharedObj: TObject;
begin
Result := FSharedObj;
end;
procedure TLock.UnLock;
begin
FCriticalSection.Release;
end;
initialization
Locks := TInterfaceList.Create;
InternalLock := TCriticalSection.Create;
finalization
InternalLock.Free;
Locks := nil
end.