如何在c++中使共享内存中的容器线程安全
How to make a container in shared memory thread safe in c++
我写了一个dll
和Visual c++ in Visual Studio 2008
,由几个进程和线程使用。
场景是这样的:
一个写入进程调用dll的init方法,该方法创建一个共享内存,并在共享内存中创建一个boost multi_index
容器,并通过调用其insert方法开始推送数据。
创建容器后,最多10个阅读器应用程序通过调用search方法在容器中执行搜索操作。
过了一段时间(假设是30秒),writer进程创建了一个delete线程,开始以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)与"access violation unable to read location ..."
中崩溃,因为删除线程改变了容器,我猜(没有删除线程它工作得很好)
我能做些什么来保持我的共享multi_index容器线程/进程的安全和同步?
谢谢…编辑:
我还有一个关于互斥锁的工作逻辑的问题。
据我所知,互斥锁只是锁定代码,以防止多次进入代码块,而不是容器本身。例如,在上面的代码中,当一个阅读器应用程序进入"搜索"方法并锁定容器时,没有其他阅读器应用程序可以进入该代码,但删除线程也可以通过输入"删除"方法来完成其任务并更改容器?
那么如何防止一次在一个共享容器上进行多个操作呢?如果你读了这个链接,第一段就说:
在DLL源代码文件中声明为全局变量的变量被编译器和链接器视为全局变量,但是每个加载给定DLL的进程都会获得该DLL全局变量的自己的副本。静态变量的作用域仅限于声明静态变量的块。因此,默认情况下,每个进程都有自己的DLL全局变量和静态变量实例。
这意味着使用DLL的每个进程都将拥有自己的单独的和非共享的互斥锁副本。因此,即使两个进程共享容器,互斥锁也将是单独的,而不是共享的,从而导致数据竞争。
既然boost已经是一个依赖项,那么最好的做法就是从进程间库开始使用互斥锁。手册和示例(在这里)。
确保始终使用定时锁定,否则如果读取器或写入器在保持它时崩溃,整个系统就会死锁。
- 从不同线程使用int64的不同字节安全吗
- 如何将元素添加到数组的线程安全函数?
- C++中的线程安全删除
- 在std::thread中,joinable()然后join()线程安全吗
- 在c++队列中使用pop和visit实现线程安全
- 以线程安全的方式调用"QQuickPaintedItem::updateImage(const QImage&image)"(no QThread)
- 全局变量 多读取器 一个写入器多线程安全?
- 共享队列的线程安全
- boost::文件系统::recursive_directory_iterator多线程安全
- 静态 constexpr 类成员变量对多线程读取是否安全?
- 以线程安全的方式转换 C/C++ 中时区名称字符串的时区偏移量
- 线程安全运算符<<
- 如何使缓存线程安全
- C++线程安全:如果只有一个线程可以写入非原子变量,但多个线程从中读取. 会遇到问题吗?
- 提升精神 V2 Qi 语法线程安全吗?
- 线程调用的函数对对象删除是否安全?
- asio 链对象线程安全吗?
- 线程安全队列 c++
- 提供对不同类型的数据(建议、代码审查)的线程安全访问的类
- 有没有更好的方法可以使此代码线程安全?线程局部静态似乎是一个生硬的工具