因此,我使用boost进程间共享内存,并使用进程间条件变量同步对其的访问。我在Windows上使用boost 1.62。我正在使用Microsoft Windows Build Tools 2015进行编译。
发生的情况是,当我使用Ctrl-C终止等待过程时,通知过程陷入了notify调用中。
这里是一个演示程序,可以重现该问题。您必须在没有任何参数的情况下运行可执行文件一次,以启动等待过程,而在有某种参数的情况下再次运行可执行文件,以启动通知过程。然后杀死第一个进程。有时您会发现打印在“ Entering notify”处停止。
#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/mapped_region.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>
#include <boost/interprocess/sync/interprocess_mutex.hpp>
#include <boost/interprocess/sync/interprocess_condition.hpp>
#include <iostream>
struct shared_data
{
boost::interprocess::interprocess_mutex mutex;
boost::interprocess::interprocess_condition condition;
bool test_bool = false;
};
int main(int argc, char *argv[])
{
using namespace boost::interprocess;
if (argc == 1) {
struct shm_remove
{
shm_remove() {
shared_memory_object::remove("MySharedMemory");
}
~shm_remove() {
shared_memory_object::remove("MySharedMemory");
}
} remover;
shared_memory_object shm(create_only, "MySharedMemory", read_write);
shm.truncate(sizeof(shared_data));
mapped_region region(shm, read_write);
void* addr = region.get_address();
shared_data* data = new (addr) shared_data;
while (true) {
scoped_lock<interprocess_mutex> lock(data->mutex);
while (!data->test_bool) {
data->condition.wait(lock);
}
std::cout << "test_bool became true" << std::endl;
data->test_bool = false;
}
}
else {
shared_memory_object shm(open_only, "MySharedMemory", read_write);
mapped_region region(shm, read_write);
shared_data* data = static_cast<shared_data*>(region.get_address());
while (true) {
{
scoped_lock<interprocess_mutex> lock(data->mutex);
data->test_bool = true;
}
std::cout << "Entering notify" << std::endl;
data->condition.notify_one();
std::cout << "Exiting notify" << std::endl;
}
}
}
如果我在调用notify_one时保持获取的锁,则不会出现问题。但是,我期望本着C ++线程实现的精神,不需要在通知时保持获得的锁。我在文档中没有找到关于此点的任何规范,只有example确实可以获取锁。
现在,鉴于我有解决问题的方法,我的问题是:
必须在调用notify
时保持锁定,但是在大多数情况下,您仍然应该这样做,因为否则某些线程(在您的情况下为进程)可能会丢失通知。请考虑以下情形:
condition.wait
之前被抢占>condition.notify_one
-但没有要通知的进程condition.wait
-并一直等待。wait
,因此不能错过该通知。这对于std::condition_variable
也适用,不仅适用于您的进程间示例。[在某些情况下,这可能不是问题(例如,因为您不会永远等待,而只是在有限的时间内),但是在此您应该非常小心。