增强named_mutex和remove()命令

发布于 2024-12-06 10:05:29 字数 1308 浏览 7 评论 0原文

我有一个可以由多个线程创建的类。但在一个函数中,代码需要受到保护,因此我决定使用 boost 进程间互斥体。每个类都会在其构造函数中创建或打开相同的互斥锁:

MyClass::MyClass()
{
       boost::interprocess::named_mutex m_Lock(
                 boost::interprocess::open_or_create, "myLock" );
}

因此现在到了调用关键代码部分的时候:

int MyClass::MyFunction()
{
       boost::interprocess::scoped_lock<boost::interprocess::named_mutex> lock(
                  m_Lock, boost::interprocess::try_to_lock);
       if(!lock)
       {
           return -1;
       }
       // else do some stuff here 
}

为了在函数之后进行清理(就像 boost 页面上所描述的那样),我在类中使用了删除命令析构函数:

MyClass::~MyClass()
{
       boost::interprocess::named_mutex::remove("myLock");
}

实际上所有这些代码都工作正常,但我有一个担忧:

正如删除命令的描述中所述:

从系统中删除指定的互斥体。出错时返回 false。从不抛出。

因此,这意味着删除命令只是将互斥锁从系统中删除 - 即使另一个线程刚刚锁定了它(我已经尝试过这种情况 - 它不再被锁定)。 所以我的问题如下: 例如,我有 3 个线程( A、B 和 C ) - 现在会发生以下情况:

  1. 进程 A 创建类的实例,调用函数并锁定它
  2. 进程 B 创建类的实例,调用函数但不能访问代码(然后等待,例如)
  3. 进程 A 完成受保护的代码并解锁
  4. 进程 B 获得对受保护代码的访问权限并锁定它
  5. 进程 A 删除该类的实例 ->删除命令被调用
  6. 进程 C 创建类的实例,调用函数并可以访问代码,因为删除命令删除了互斥体 -->错误!

所以现在有人可能会说“那就不要调用删除!” - 那么这可能吗?我的意思是,由于named_mutex写入系统,我怀疑即使程序结束,它也会在没有显式调用的情况下被删除。 有人有帮助吗?

I have a class which can be created by multiple threads. But at one function the code needs to be protected, so I decided to use the boost interprocess mutex. Every class creates or opens the same Mutex in it's constructor:

MyClass::MyClass()
{
       boost::interprocess::named_mutex m_Lock(
                 boost::interprocess::open_or_create, "myLock" );
}

So now there comes the point where the critical code part is called:

int MyClass::MyFunction()
{
       boost::interprocess::scoped_lock<boost::interprocess::named_mutex> lock(
                  m_Lock, boost::interprocess::try_to_lock);
       if(!lock)
       {
           return -1;
       }
       // else do some stuff here 
}

To clean up after the function ( and like its described on the boost page ) I use the remove command in my class destructor:

MyClass::~MyClass()
{
       boost::interprocess::named_mutex::remove("myLock");
}

Actually all this code works fine, but there is one concern I have:

As it is said in the description of the remove command :

Erases a named mutex from the system. Returns false on error. Never throws.

So that means the remove command just erases the Mutex out of the system - even if another thread has just locked it ( I tried this case already - it isn't locked then anymore ).
So my problem is the following:
For example I have 3 Threads ( A, B and C ) - now the following happens:

  1. Process A creates an Instance of the class, calls the function and locks it
  2. Process B creates an Instances of the class, calls the function but can't access code ( then waits e.g. )
  3. Process A finishes with the protected code and it gets unlocked
  4. Process B gains access to the protected code and locks it
  5. Process A deletes the Instance of the class -> the remove command is called
  6. Process C creates an Instance of the class, calls the function and can access the code since the remove command erased the Mutex --> Error!

So now someone may say " Then don't call remove! " - Well is that possible? I mean since the named_mutex writes to the system I doubt it is erased without an explicit call, even if the program ends.
Anyone has some help?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

以可爱出名 2024-12-13 10:05:29

来自 boost 文档,< code>remove 调用,是不必要的。 named_mutex 的析构函数会自动向操作系统表明该进程不再需要该资源。您可能只需要依靠析构函数的内置行为进行清理就可以了。

如果显式调用remove,则可能会导致尝试使用指定互斥体的任何其他进程或线程对该互斥体的任何操作失败。根据您的使用安排方式,这可能会导致数据争用或在其他进程中引发崩溃/异常。

~named_mutex();

销毁*this并表明调用过程已完成
使用该资源。析构函数将释放任何系统
系统为此进程分配的资源
资源。资源仍然可以通过调用 open 再次打开
构造函数重载。要从系统中删除资源,请使用
删除()。

From the boost docs, the remove call, is unnecessary. The destructor of named_mutex will automatically take care indicating to the OS that the process no longer needs the resource. You're probably fine with just relying upon the built-in behavior of the destructor for cleanup.

If you explicitly call remove, you'll likely cause any other processes or threads attempting to use the named mutex to fail on any operations on the mutex. Depending on how your usage is orchestrated, this could either cause data races or crashing/exceptions being thrown in other processes.

~named_mutex();

Destroys *this and indicates that the calling process is finished
using the resource. The destructor function will deallocate any system
resources allocated by the system for use by this process for this
resource. The resource can still be opened again calling the open
constructor overload. To erase the resource from the system use
remove().

柠北森屋 2024-12-13 10:05:29

您可能需要一个互斥锁的共享使用计数器。在析构函数中锁定互斥体,将其递减,如果递减后它为零,则释放仍然锁定的互斥体。这样你就可以防止你当前的竞争状况。

You probably need a shared usage counter for the mutex. Lock the mutex in the destructor, decrement it, and if it's zero after the decrement, deallocate the still locked mutex. You will prevent your current race condition by that.

捂风挽笑 2024-12-13 10:05:29

根据 boost 手册:

  1. 这是一个具有全局名称的互斥体,因此可以从不同的进程中找到它。但是,该互斥体不能放置在共享内存中。 @Toby
  2. 析构函数将释放系统分配给该资源的进程使用的任何系统资源。仍然可以调用 open 构造函数重载再次打开资源。要从系统中删除资源,请使用remove()。

我想上面的内容应该已经解答了你的疑问。

According to the boost manual:

  1. This is a mutex with a global name, so it can be found from different processes. However, this mutex can't be placed in shared memory. @Toby
  2. The destructor function will deallocate any system resources allocated by the system for use by this process for this resource. The resource can still be opened again calling the open constructor overload. To erase the resource from the system use remove().

I think the above should have addressed your questions.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文