c++ - 如何在 C++ 中使共享内存线程安全的容器

标签 c++ multithreading boost thread-safety shared-memory

我在 Visual Studio 2008 中使用 Visual c++ 编写了一个 dll,它被多个进程和线程使用。

场景是这样的:

一个writer进程调用dll的“init”方法,该方法创建共享内存,并在共享内存中创建一个boost multi_index容器,调用其insert方法开始推送数据。

容器创建后,最多 10 个阅读器应用程序开始通过调用搜索方法在其中执行搜索操作。

一段时间后(假设是 30 秒)写入进程创建一个删除线程,该线程开始删除容器中的数据(最旧的数据),频率为 1 次删除操作/秒。

代码的头文件 (hpp) 如下所示:

class SharedMemoryContainer
{     

private:

    typedef boost::interprocess::allocator<SharedObj, managed_shared_memory::segment_manager> ShmemAllocator;

    typedef multi_index_container<
        SharedObj, 
            indexed_by<    
                random_access<>, 
                ordered_non_unique< member<SharedObj, unsigned _int64, &SharedObj::id >
            >, ShmemAllocator
    > SharedMemoryContainerType;


    struct compare
    {
        unsigned _int64 _compare; 
        int _trackNo;
        compare(unsigned _int64 id, int trackNo) : _compare(id), _trackNo(trackNo) {}
        bool operator()(SharedObj const& item) const {return (item.id == _compare && item.trackNo == _trackNo);};
    };


    static boost::mutex mutex_; // the mutex that i used to synchronize the operations

    /*
    .
    .
    some more variables and methods...
    .
    .
    */

public:

    bool insert (/*.. parameters ..*/); 

    SharedObj search (/*.. parameters ..*/);

    bool delete ();

    /*
    .
    .
    some more variables and methods...
    .
    .
    */
};

在实现 (cpp) 文件中,我使用这样的互斥体:

boost::mutex SharedMemoryContainer::mutex_; // for the static mutex

// insert new data to shared container
bool SharedMemoryContainer::insert(/*.. parameters ..*/) 
{
    boost::mutex::scoped_lock m(mutex_);
    bool result;
        try
        {
            // Make the insertion here
        }
        catch(interprocess_exception &ex)
        {
            std::cout << "Error in Insert!" << std::endl <<ex.what() << std::endl;
            return false;
        }
    return result;
}

// reader applications perform search in shared container
SharedObj SharedMemoryContainer::search(/*.. parameters ..*/) 
{
    boost::mutex::scoped_lock m(mutex_);

    IndexType& idIndex = myContainer->get<0>();
    IteratorType current = std::find_if(idIndex.begin(), idIndex.end(), compare(id, trackNo));
    /*
    .
    .
    other operations
    .
    .
    */
}

// it always delete the oldest one
bool SharedMemoryContainer::delete() 
{
    boost::mutex::scoped_lock m(mutex_);

    IndexType& idIndex = myContainer->get<0>();
    it first = myContainer->begin();            
    idIndex.erase(first); 
}

这种互斥使用似乎不起作用。因为它总是在不同的时间崩溃(我的意思是它会改变,它可能在 40 秒或 5 分钟等之后......)

由于删除线程更改,它在 compare struct(在搜索 - find_if 中调用)中崩溃,“访问冲突无法读取位置...”我猜的容器(它在没有删除线程的情况下工作正常)

我可以做些什么来保持我的共享 multi_index 容器线程/进程安全和同步?

谢谢...

编辑:

关于互斥量的工作逻辑,我还有一个问题。

据我所知,互斥体只是锁定代码以防止多次进入代码块而不是容器本身。因此,例如,在上面的代码中,当阅读器应用程序进入“搜索”方法并锁定容器时,其他阅读器应用程序无法输入代码,但删除线程也可以通过输入“删除”方法并更改容器来完成其任务?

那么如何防止一次对一个共享容器进行多次操作呢?

最佳答案

如果你read this link第一段说:

Variables that are declared as global in a DLL source code file are treated as global variables by the compiler and linker, but each process that loads a given DLL gets its own copy of that DLL's global variables. The scope of static variables is limited to the block in which the static variables are declared. As a result, each process has its own instance of the DLL global and static variables by default.

这意味着使用您的 DLL 的每个进程都将拥有自己的单独非共享 互斥体拷贝。因此,即使两个进程共享容器,互斥量也将是独立的并且不会共享,从而导致数据竞争。

关于c++ - 如何在 C++ 中使共享内存线程安全的容器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23535257/

相关文章:

C++ - 占位符如何工作(特别是在 boost::type_erasure 中)?

c++ - 为什么 boost::enable_if 不会导致重复重载方法编译错误

c++ - Boost::variant 的多态 setter

c++ - 将项目源代码与 CMake 下的 boost 测试链接起来

c++ - 就地 union 排序 vector

c++ - 如何实现模板内部类函数(C++)

c++ - 从 Boost 线程返回 Double

java - OpenJDK11 jstack输出解释

c++ - 在 C++ 中使用 unordered_set 作为 unordered_map 的键时出现的问题

java - 为什么Java中Swing GUI关闭后新线程也会退出