如何在C++或Winapi中转移同步对象的所有权

How to transfer ownership of a synchronization object in C++ or Winapi?

本文关键字:同步 转移 对象 所有权 Winapi C++      更新时间:2023-10-16

是否可以将互斥体、关键部分等的所有权从第一个线程转移到第二个线程,而不让任何第三个线程同时获取所有权?关键部分的文档禁止在调用EnterCriticalSection的线程之外的线程中调用LeaveCriticalSection:

如果线程在没有指定关键节对象的所有权时调用LeaveCriticalSection,则会发生错误,可能会导致另一个使用EnterCriticalSection的线程无限期等待。

但在我的场景中,我需要在与获取同步对象的线程不同的线程中准确地释放同步对象,这样其他(第三)线程就无法同时获得同步对象的所有权(从第一个线程获取同步对象到第二个线程释放同步对象)。C++线程或WinAPI调用的解决方案将适合我的需求。

否,不支持线程所有权转移。此外,我坚信,任何依赖锁所有权的设计都是有缺陷的,并且会在未来造成麻烦。

然而,如果所有权转移仅用于从不同于接收锁的线程释放锁,则有两种选择:

  • 使用信号量。根据设计,它们可以从任何线程中释放
  • 在未定义的行为中激活并从不拥有它的线程中释放互斥对象。你需要了解这会带来什么后果

未定义的行为

从不拥有互斥锁的线程释放互斥锁是未定义的。但是,可以使用这些代码对应用程序进行编码。您将遇到的问题是,如果锁定互斥的线程在一个CPU上运行,而解锁发生在另一个CPU,那么数据同步可能不会发生在非缓存一致的芯片上。因此,未受另一个同步保护的数据将"脏"。然而,如果没有这样的数据——例如,互斥体确实在"信号量"函数中使用,并且不保护任何数据——这可能是可以接受的。