[英]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.