Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lock and unlock resources with single command

I am working with threads and that's the reason I use mutexes for locking shared resources. The base usage of locking is to put resources within Lock/unlock block.

procedure RefreshData;
begin    
   DataLock;
      GetData;
      GetSettings;
      CheckValues;
      ...
   DataUnlock;
end;

Because there is always a pair Lock/Unlock I started thinking about simplified lock/unlock approach which would automatical unlock resources when not needed anymore.

So my idea was to introduce new procedure which would take as an input parameter a reference to precedure. This will give me ability to use anonymous method.

Code would be something like:

type TBaseProc = reference to procedure;

procedure TMyObject.LockMethod(AMeth: TBaseProc);
begin
  DataLock;
  try
    AMeth;
  finally
    DataUnlock;
  end;
end;


procedure TForm1.RefreshData;
begin
  MyObject.LockMethod(
   procedure 
   begin
     GetData;
     GetSettings;
     CheckValues;
     ...
   end;
  );

end;

Has this approach any sense or is there better or even easier solution to this?

Thanks and regards.

like image 837
Nix Avatar asked Nov 22 '22 08:11

Nix


1 Answers

This approach is far from perfect because you have one lock per entire application, as I understood from your code. It is better when each independent data entity has its own lock. So you would have an abstract class like this:

type
  TAbstractData = class
    private
       CriticalSection: TRtlCriticalSection
    public
       constructor Create;
       procedure Lock;
       procedure Unlock;
       destructor Destroy; override;
  end;

Then inherit other classes from this abstract class that implements locking.

       constructor TAbstractData.Create;
       begin
         inherited Create;
         InitializeCriticalSection(CriticalSection);
       end;

       procedure TAbstractData.Lock;
       begin
         EntercriticalSection(CriticalSection);
       end;
 
       procedure TAbstractData.Unlock;
       begin
         LeaveSection(CriticalSection);
       end;

       procedure TAbstractData.Destroy; 
       begin
         DeleteCriticalSection(CriticalSection);
         inherited Destroy;
       end;

A CriticalSection is the most efficient synchronization class implemented in Windows. It is virtually free - consumes almost no system resources unless there is thread contention, and does not invoke expensive context switch when just one thread uses the data.

After I have submitted the answer, I have found a good article on the Internet - http://blog.synopse.info/post/2016/01/09/Safe-locks-for-multi-thread-applications - the author recommends a similar approach.

like image 131
Maxim Masiutin Avatar answered Dec 05 '22 09:12

Maxim Masiutin