簡體   English   中英

如何在C ++中使共享內存線程中的容器安全

[英]How to make a container in shared memory thread safe in c++

Visual c++ in Visual Studio 2008中用Visual c++ in Visual Studio 2008編寫了一個dll ,供多個進程和線程使用。

該場景是這樣的:

一個編寫器進程調用dll的“ init”方法,該方法創建一個共享內存,並在共享內存中創建一個boost multi_index容器,並通過調用其insert方法開始推送數據。

創建容器后,最多有10個閱讀器應用程序通過調用search方法開始在其中執行搜索操作。

一段時間(例如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分鍾后等等)。

由於“刪除"access violation unable to read location ..."線程更改了我猜想的容器,它在compare struct (在搜索中被調用-find_if)中崩潰,並帶有"access violation unable to read location ..." (如果沒有刪除線程,它可以正常工作)

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

謝謝...

編輯:

關於互斥的工作邏輯,我還有一個問題。

就我閱讀互斥鎖而言,它只是鎖定代碼以防止多次輸入代碼塊,而不是容器本身。 因此,例如,在上面的代碼中,當閱讀器應用程序進入“搜索”方法並鎖定容器時,沒有其他閱讀器應用程序可以輸入代碼,但是刪除線程也可以通過輸入“刪除”方法來完成其任務並更改容器?

那么如何防止一次對一個共享容器進行多次操作呢?

如果您閱讀此鏈接,則第一段說明:

DLL源代碼文件中聲明為全局的變量被編譯器和鏈接器視為全局變量,但是加載給定DLL的每個進程都會獲得該DLL全局變量的自己的副本。 靜態變量的范圍僅限於聲明靜態變量的塊。 結果,默認情況下,每個進程都有其自己的DLL全局和靜態變量實例。

這意味着每個使用您的DLL的進程將擁有它自己的互斥體的單獨 且未共享的副本。 因此,即使兩個進程共享該容器,該互斥鎖也將是獨立的並且不會共享,從而導致數據爭用。

由於您已經將boost作為依賴項,所以最好的做法是開始使用進程間庫中的互斥鎖。 手冊和示例( 此處 )。

確保始終使用定時鎖定,否則如果讀取器或寫入器在保持鎖定狀態時崩潰,則會導致整個系統死鎖。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM