提升 named_mutex 和 remove() 命令
Posted
技术标签:
【中文标题】提升 named_mutex 和 remove() 命令【英文标题】:Boost named_mutex and remove() command 【发布时间】:2011-09-26 12:43:44 【问题描述】:我有一个可以由多个线程创建的类。但是在一个函数中,代码需要受到保护,所以我决定使用 boost 进程间互斥锁。每个类都在其构造函数中创建或打开相同的 Mutex:
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 页面上描述的那样),我在我的类析构函数中使用了 remove 命令:
MyClass::~MyClass()
boost::interprocess::named_mutex::remove("myLock");
实际上所有这些代码都可以正常工作,但我有一个担忧:
正如删除命令的描述中所说:
从系统中删除一个命名的互斥体。出错时返回 false。从不扔。
所以这意味着 remove 命令只是将 Mutex 从系统中删除 - 即使另一个线程刚刚锁定它(我已经尝试过这种情况 - 它不再被锁定)。 所以我的问题如下: 例如,我有 3 个线程( A、B 和 C ) - 现在发生以下情况:
-
进程 A 创建类的实例,调用函数并锁定它
进程 B 创建类的实例,调用函数但无法访问代码(然后等待例如)
进程 A 使用受保护的代码完成并解锁
进程 B 获得对受保护代码的访问权并将其锁定
进程 A 删除类的实例 -> 调用删除命令
进程 C 创建类的实例,调用函数并可以访问代码,因为删除命令删除了互斥锁 --> 错误!
所以现在有人可能会说“那么不要调用 remove!” - 这可能吗?我的意思是,由于 named_mutex 写入系统,我怀疑它在没有显式调用的情况下被删除,即使程序结束。 有人帮忙吗?
【问题讨论】:
我对您的问题以及术语“线程”和“进程”的相互使用感到困惑。你在处理哪个?线程?还是流程?如果您只是在单个进程中使用多线程,则命名的 mutice 通常具有极其微不足道的效用。 您对此感到抱歉 - 我只是在写作时有点困惑。其实我有不同的过程。正如您所说,只有线程实际上不需要命名互斥锁。 【参考方案1】:从boost docs 调用,remove
是不必要的。 named_mutex
的析构函数会自动向操作系统表明该进程不再需要该资源。仅仅依靠析构函数的内置行为进行清理可能没问题。
如果您显式调用 remove,您可能会导致任何其他尝试使用命名互斥锁的进程或线程在互斥锁上的任何操作上失败。根据您的使用情况如何编排,这可能会导致数据争用或在其他进程中引发崩溃/异常。
~named_mutex();
销毁 *this 表示调用过程结束 使用资源。析构函数将释放任何系统 系统分配给这个进程使用的资源 资源。资源仍然可以再次打开调用 open 构造函数重载。要从系统中删除资源,请使用 删除()。
【讨论】:
因此,如果我做对了,只要我不调用 remove() 资源就会留在系统中(即使调用了析构函数)-但这没关系,因为析构函数告诉资源被“解锁”的操作系统,所以另一个进程可以锁定它?是这样吗?? 我自己没怎么玩过它们,但我认为如果使用互斥锁的进程数变为零,资源将被释放。我的 linux 机器上 sem_close 的手册页说:DESCRIPTION sem_close() 关闭 sem 引用的命名信号量,允许释放系统为调用此信号量的调用进程分配的任何资源。 好吧,我昨天做了一些研究和反复试验。互斥锁的资源位于共享内存 ( /dev/shm/ ) 中。创建后,它将一直留在那里,直到您调用 remove() 或系统重新启动。 (或者你做任何其他事情来清除共享内存,例如自己擦除它)。对象本身包含有关它是否被锁定的信息。当互斥体被破坏时,它只是被解锁但没有被删除!所以唯一的问题可能是程序严重崩溃并且无法调用析构函数并且对象保持锁定状态。 但如果发生这种情况,我认为有更严重的错误,所以我实际上并不担心第一种方式的互斥锁!所以我想说->问题解决了!谢谢!【参考方案2】:您可能需要一个共享的互斥量计数器。将互斥锁锁定在析构函数中,将其递减,如果递减后为零,则释放仍锁定的互斥锁。你会阻止你当前的比赛条件。
【讨论】:
【参考方案3】:根据boost手册:
-
这是一个具有全局名称的互斥锁,因此可以从不同的进程中找到它。但是,这个互斥锁不能放在共享内存中。 @托比
析构函数将释放系统分配的任何系统资源,供此进程用于此资源。资源仍然可以通过调用 open 构造函数重载再次打开。要从系统中删除资源,请使用 remove()。
我认为以上内容应该已经解决了您的问题。
【讨论】:
以上是关于提升 named_mutex 和 remove() 命令的主要内容,如果未能解决你的问题,请参考以下文章
boost::named_mutex: 最后一个进程关闭时安全清理
boost::named_mutex: 最后一个进程关闭时安全清理
boost::interprocess::named_mutex 是不是需要存储在共享内存中?