问题描述
我的场景:一台服务器和一些客户端(虽然不多).服务器一次只能响应一个客户端,因此必须排队.我正在使用互斥锁 (boost::interprocess::interprocess_mutex
) 来执行此操作,并包裹在 boost::interprocess::scoped_lock
中.
My scenario: one server and some clients (though not many). The server can only respond to one client at a time, so they must be queued up. I'm using a mutex (boost::interprocess::interprocess_mutex
) to do this, wrapped in a boost::interprocess::scoped_lock
.
问题是,如果一个客户端在持有互斥锁时意外死亡(即没有析构函数运行),其他客户端就会遇到麻烦,因为它们正在等待该互斥锁.我考虑过使用定时等待,所以如果我的客户端等待了 20 秒并且没有获得互斥锁,它会继续与服务器对话.
The thing is, if one client dies unexpectedly (i.e. no destructor runs) while holding the mutex, the other clients are in trouble, because they are waiting on that mutex. I've considered using timed wait, so if I client waits for, say, 20 seconds and doesn't get the mutex, it goes ahead and talks to the server anyway.
这种方法的问题:1)它每次都这样做.如果它处于循环中,不断与服务器通信,则每次都需要等待超时.2) 如果有三个客户端,其中一个在持有互斥锁时死亡,另外两个将等待 20 秒并同时与服务器通信——这正是我试图避免的.
Problems with this approach: 1) it does this everytime. If it's in a loop, talking constantly to the server, it needs to wait for the timeout every single time. 2) If there are three clients, and one of them dies while holding the mutex, the other two will just wait 20 seconds and talk to the server at the same time - exactly what I was trying to avoid.
那么,我怎么能对客户说,嘿,看来这个互斥体已被放弃,取得它的所有权"?
推荐答案
很遗憾,boost::interprocess API 不支持此功能.但是,您可以通过几种方式来实现它:
Unfortunately, this isn't supported by the boost::interprocess API as-is. There are a few ways you could implement it however:
如果您在支持 pthread_mutexattr_setrobust_np 的 POSIX 平台上,请编辑 boost/interprocess/sync/posix/thread_helpers.hpp 和 boost/interprocess/sync/posix/interprocess_mutex.hpp 以使用强大的互斥锁,并以某种方式处理 EOWNERDEAD从 pthread_mutex_lock 返回.
If you are on a POSIX platform with support for pthread_mutexattr_setrobust_np, edit boost/interprocess/sync/posix/thread_helpers.hpp and boost/interprocess/sync/posix/interprocess_mutex.hpp to use robust mutexes, and to handle somehow the EOWNERDEAD return from pthread_mutex_lock.
如果您在其他平台上,您可以编辑 boost/interprocess/sync/emulation/interprocess_mutex.hpp 以使用生成计数器,锁定标志位于低位.然后您可以创建一个回收协议,该协议将在锁定字中设置一个标志以指示待处理的回收,然后在超时后进行比较和交换以检查同一代是否仍在锁定字中,如果是则替换它具有锁定的下一代值.
If you are on some other platform, you could edit boost/interprocess/sync/emulation/interprocess_mutex.hpp to use a generation counter, with the locked flag in the lower bit. Then you can create a reclaim protocol that will set a flag in the lock word to indicate a pending reclaim, then do a compare-and-swap after a timeout to check that the same generation is still in the lock word, and if so replace it with a locked next-generation value.
如果您在 Windows 上,另一个不错的选择是使用本机互斥对象;无论如何,它们可能比忙着等待更有效率.
If you're on windows, another good option would be to use native mutex objects; they'll likely be more efficient than busy-waiting anyway.
您可能还想重新考虑使用共享内存协议 - 为什么不改用网络协议?
You may also want to reconsider the use of a shared-memory protocol - why not use a network protocol instead?
这篇关于如何获得废弃的 boost::interprocess::interprocess_mutex 的所有权?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!