首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在c++中使共享内存线程中的容器安全

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

Stack Overflow用户
提问于 2014-05-08 07:20:32
回答 2查看 1.7K关注 0票数 3

我用Visual c++ in Visual Studio 2008编写了一个Visual c++ in Visual Studio 2008,它由多个进程和线程使用。

情况是这样的:

一个编写器进程调用dll的"init“方法,此方法在共享内存中创建共享内存并创建boost multi_index容器,并通过调用其插入方法开始推送数据。

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

一段时间后(比方说30秒),编写进程创建了一个删除线程,该线程开始删除容器中的数据(最老的),频率类似于每秒1次删除操作。

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

代码语言:javascript
复制
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)文件中,我使用互斥对象,如下所示:

代码语言:javascript
复制
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 (在search -find_if中被调用)与"access violation unable to read location ..."崩溃,因为删除线程改变了容器,我猜(没有删除线程,它工作得很好)。

如何保持共享的multi_index容器线程/进程的安全和同步?

谢谢..。

编辑:

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

据我所知,互斥锁只是锁定代码,以防止多个条目进入代码块,而不是容器本身。例如,在上面的代码中,当读取器应用程序进入"search“方法并锁定容器时,其他任何阅读器应用程序都无法输入代码,但删除线程也可以通过输入" delete”方法来执行任务并更改容器?

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

EN

回答 2

Stack Overflow用户

发布于 2014-05-08 07:27:44

如果您在阅读此链接第一段中指出:

编译器和链接器将在DLL源代码文件中声明为全局变量的变量视为全局变量,但加载给定DLL的每个进程都会获得该DLL的全局变量的副本。静态变量的范围仅限于声明静态变量的块。因此,默认情况下,每个进程都有自己的DLL全局变量和静态变量的实例。

这意味着使用DLL的每个进程都将拥有自己独立的互斥体的未共享副本。因此,即使两个进程共享容器,互斥将是独立的,而不是共享的,从而导致数据竞争。

票数 4
EN

Stack Overflow用户

发布于 2014-05-08 07:31:24

由于您已经将boost作为依赖项,所以最好的操作方法就是从进程间库开始使用互斥对象。手册和示例(这里)。

确保始终使用定时锁定,就像读取器或写入器在保存整个系统死锁时崩溃一样。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23535257

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档