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

Posted

技术标签:

【中文标题】使用单个命令锁定和解锁资源【英文标题】:Lock and unlock resources with single command 【发布时间】:2015-01-18 01:17:01 【问题描述】:

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

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

因为总是有一对锁定/解锁,所以我开始考虑简化的锁定/解锁方法,它会在不再需要时自动解锁资源。

所以我的想法是引入新的过程,它将作为输入参数对 precedure 的引用。这将使我能够使用匿名方法。

代码类似于:

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;

这种方法有什么意义吗?或者有更好甚至更简单的解决方案吗?

感谢和问候。

【问题讨论】:

你是否关心性能? 最简单的解决方案是,如果编译器对 Lock() 语句具有原生支持,例如 C#:msdn.microsoft.com/en-us/library/c5kehkcz.aspx。我个人将代码模板用于锁定/解锁对。 @David:是的,我关心性能。有没有估计多少开销会导致这种方法?我猜锁定/解锁对在性能方面仍然是更好的方法。 这是一个带有接口的nice approach 除此之外......只是一个简短的问题。在同一线程中嵌套锁定/解锁块时,例如:mtx1.Acquire; mtx1.获取;做一些东西; mtx1.release; mtx1.release。据我所知,当互斥锁已由同一线程拥有时不会发生锁定,但释放情况如何?哪个版本将解锁资源,第一个或第二个调用?我不确定,但我想我在某处读到系统有内部计数,所以我认为最后一个版本将真正解锁资源。我说的对吗? 【参考方案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——作者推荐了类似的做法。

【讨论】:

以上是关于使用单个命令锁定和解锁资源的主要内容,如果未能解决你的问题,请参考以下文章

10分钟后锁定和解锁屏幕时发生的崩溃如何解决?

如何在 Windows 中为可以锁定(只读)和解锁驱动器的 diskpart cmd 创建批处理文件

如何锁定和解锁 SQL SERVER 表?

在同一个互斥锁上的锁定和解锁顺序是不是一致?

(Discord.py) 如何锁定和解锁语音通道

如何从服务中可靠地捕获 Windows 登录、注销、锁定和解锁事件?