通知boost-interprocessing条件变量时未保持锁定会导致问题

问题描述 投票:0回答:1

因此,我使用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确实可以获取锁。

现在,鉴于我有解决问题的方法,我的问题是:

    是否需要在通知预期的同时获得锁并且只能正确使用,还是有错误?
  1. 如果是预期的用法,为什么?
c++ multithreading concurrency multiprocessing boost-interprocess
1个回答
0
投票
您不必

必须在调用notify时保持锁定,但是在大多数情况下,您仍然应该这样做,因为否则某些线程(在您的情况下为进程)可能会丢失通知。请考虑以下情形:

    进程1获取锁并检查条件,但是在调用condition.wait之前被抢占>
  • 进程2调用condition.notify_one-但没有要通知的进程
  • 您杀死进程2
  • 现在进程1最终调用condition.wait-并一直等待。
  • 通过在调用notify之前获取锁,您可以确保其他进程已经调用wait,因此不能错过该通知。这对于std::condition_variable也适用,不仅适用于您的进程间示例。

[在某些情况下,这可能不是问题(例如,因为您不会永远等待,而只是在有限的时间内),但是在此您应该非常小心。

© www.soinside.com 2019 - 2024. All rights reserved.