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

Ste*_*eve 6 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;
Run Code Online (Sandbox Code Playgroud)

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

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

有任何想法吗?

Zoë*_*son 15

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

初始化期间:

Mutex := CreateMutex(nil, False, 'Connections');
if Mutex = 0 then
  RaiseLastOSError;
Run Code Online (Sandbox Code Playgroud)

当您想要访问资源时

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

在定稿期间

CloseHandle(Mutex);
Run Code Online (Sandbox Code Playgroud)

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

  • 克雷格是对的。我的建议是*永远*不要为第二个参数传递`True`。原因是当函数返回时,您不知道您是否真正拥有互斥锁。此外,在创建时,您可能无论如何都不需要拥有互斥锁。在程序启动时创建互斥锁*一次*。然后在程序运行时获取并释放它。当您的程序终止时,关闭句柄。不要在每次需要拥有互斥锁时创建和销毁它。 (2认同)

mgh*_*hie 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;
Run Code Online (Sandbox Code Playgroud)

请注意,我选择使用单元中的TMutexSyncObjs,这简化了操作.