如何使用互斥锁保护公共资源?

时间:2010-03-18 15:15:28

标签: delphi mutex

我有一个公共资源,我想要1,只有我的应用程序的一个实例(或它的COM API)可以随时访问。我曾尝试使用互斥锁保护此资源,但是当主机dotnet应用程序的多个线程尝试访问COM对象时,似乎没有释放互斥锁。这是我用来保护资源的代码。

repeat
  Mutex := CreateMutex(nil, True, PChar('Connections'));
until (Mutex <> 0) and (GetLastError <> ERROR_ALREADY_EXISTS);
  try
    //use resource here!
  finally
    CloseHandle(Mutex);
  end;

如果我同时运行线程,第一个线程就会通过(显然是第一个创建互斥锁的线程),但后续线程会在重复循环中被捕获。如果我以5秒的间隔运行每个线程,那么一切都没问题。

我怀疑我在这里没有正确使用互斥锁,但我发现很少有关于如何执行此操作的文档。

有什么想法吗?

2 个答案:

答案 0 :(得分:15)

您使用的互斥锁是错误的。您应该等待它并释放它,而不是不断重新创建它。

初始化期间:

Mutex := CreateMutex(nil, False, 'Connections');
if Mutex = 0 then
  RaiseLastOSError;

当您想要访问资源时

if WaitForSingleObject(Mutex, INFINITE) <> WAIT_OBJECT_0 then
  RaiseLastOSError;
try
  // Use resource here
finally
  ReleaseMutex(Mutex)
end;

在定稿期间

CloseHandle(Mutex);

此外,由于互斥锁是全局的,因此您应该选择比名称的“连接”更独特的东西。我们在我们的末尾添加了一个GUID。

答案 1 :(得分:11)

尝试使用这个简单的演示代码。启动应用程序的多个实例,您可以从背景颜色中看到它们如何共享互斥锁:

procedure TForm1.FormCreate(Sender: TObject);
begin
  fMutex := SyncObjs.TMutex.Create(nil, False, 'GlobalUniqueName');
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  fMutex.Free;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Color := clRed;
  Update;
  fMutex.Acquire;
  try
    Color := clGreen;
    Update;
    Sleep(5 * 1000);
  finally
    fMutex.Release;
  end;
  Color := clBtnFace;
end;

请注意,我选择使用TMutex单元中的SyncObjs类,这简化了事情。