使用单个命令锁定和解锁资源。

5

我正在使用线程,这就是我使用互斥锁来锁定共享资源的原因。锁定的基本用法是将资源放入锁定/解锁块中。

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

因为总是存在配对的 Lock/Unlock,我开始思考一种简化的锁定/解锁方法,可以在不需要时自动解锁资源。
所以我的想法是引入一个新的过程,该过程将以指向过程的引用作为输入参数。这将使我能够使用匿名方法。
代码可能如下:
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;

这种方式有意义吗?还是有更好甚至更简单的解决方案吗?谢谢和问候。

你关心性能吗? - David Heffernan
2
最简单的解决方案是编译器具有像C#中的Lock()语句一样的本地支持:http://msdn.microsoft.com/en-us/library/c5kehkcz.aspx。个人而言,我使用锁定/解锁对的代码模板。 - iPath ツ
3
这里有一个使用接口的“好方法”。 - TLama
除此之外...只有一个简短的问题。当在同一线程中嵌套Lock/Unlock块时,例如:mtx1.Acquire; mtx1.Acquire; DoSomeStuff; mtx1.release; mtx1.release。我知道当互斥量已经被同一线程拥有时,锁定不会发生,但释放呢?哪个释放将解锁资源,第一个还是第二个调用?我不确定,但我想我在某个地方读到系统有内部计数,所以我认为最后一个Release将真正解锁资源。我对吗? - Nix
关于你的另一个问题,请不要在评论中提出新问题。提出一个新问题,并明确你使用的互斥锁类型。它是递归互斥锁吗?如果是,那么最终释放实际上才会释放。没有其他方式是有意义的。 - David Heffernan
显示剩余2条评论
1个回答

1
这种方法远非完美,因为根据您的代码,您只有一个锁用于整个应用程序。更好的方法是每个独立的数据实体都有自己的锁。因此,您可以拥有像这样的抽象类:
type
  TAbstractData = class
    private
       CriticalSection: TRtlCriticalSection
    public
       constructor Create;
       procedure Lock;
       procedure Unlock;
       destructor Destroy; override;
  end;

然后从实现锁定的抽象类中继承其他类。

       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;

一个 CriticalSection 是Windows实现的最有效的同步类。它几乎是免费的 - 除非有线程争用,否则几乎不消耗系统资源,并且当只有一个线程使用数据时不会引发昂贵的上下文切换。
在我提交答案之后,我在互联网上找到了一篇好文章 - http://blog.synopse.info/post/2016/01/09/Safe-locks-for-multi-thread-applications - 作者推荐了类似的方法。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接