如何基于Boost Interprocess结合互斥锁与条件变量跨内存共享vector?
实现带互斥锁与条件变量的Boost Interprocess共享vector
我来帮你搞定这个跨进程安全共享vector的需求!你找到的基础代码已经实现了共享vector的核心,但要让它在多进程下安全访问,我们需要把互斥锁和条件变量也放在共享内存中(普通的std同步原语只能用于进程内线程)。下面是改造后的完整实现,包含生产者和消费者示例:
核心思路
- 用一个结构体封装共享资源:把
interprocess_mutex、interprocess_condition和共享vector放在一起,确保所有进程都能访问到同一组同步原语。 - 使用Boost Interprocess的
find_or_construct来安全创建/获取共享内存中的对象,避免重复初始化。 - 访问vector时必须先锁定互斥锁,操作完成后解锁;用条件变量实现生产者-消费者的同步(比如生产者通知消费者有新元素,消费者等待元素可用)。
完整代码示例
生产者进程代码
#include <boost/interprocess/managed_shared_memory.hpp> #include <boost/interprocess/containers/vector.hpp> #include <boost/interprocess/allocators/allocator.hpp> #include <boost/interprocess/sync/interprocess_mutex.hpp> #include <boost/interprocess/sync/interprocess_condition.hpp> #include <chrono> #include <thread> #include <iostream> using namespace boost::interprocess; // 定义共享内存中的分配器 using ShmemAllocator = allocator<int, managed_shared_memory::segment_manager>; // 定义共享vector类型 using MyVector = vector<int, ShmemAllocator>; // 封装共享资源的结构体,包含同步原语和vector struct SharedData { interprocess_mutex mutex; interprocess_condition cond; MyVector vec; // 构造函数:用共享内存分配器初始化vector SharedData(const ShmemAllocator& alloc) : vec(alloc) {} }; int main() { // 先清理可能存在的旧共享内存 shared_memory_object::remove("MySharedMemory"); // 创建共享内存段 managed_shared_memory segment(create_only, "MySharedMemory", 65536); // 获取共享内存的分配器 const ShmemAllocator alloc(segment.get_segment_manager()); // 在共享内存中创建SharedData实例 SharedData* shared_data = segment.construct<SharedData>("SharedData")(alloc); // 生产者逻辑:往vector里添加元素,然后通知消费者 for (int i = 0; i < 5; ++i) { // 加锁 scoped_lock<interprocess_mutex> lock(shared_data->mutex); shared_data->vec.push_back(i); std::cout << "Producer added: " << i << std::endl; // 通知等待的消费者 shared_data->cond.notify_one(); // 解锁(scoped_lock自动释放) std::this_thread::sleep_for(std::chrono::milliseconds(500)); } // 等待一下,让消费者有时间处理完所有元素 std::this_thread::sleep_for(std::chrono::seconds(2)); // 销毁共享内存中的对象(可选,也可以让消费者最后清理) segment.destroy<SharedData>("SharedData"); shared_memory_object::remove("MySharedMemory"); return 0; }
消费者进程代码
#include <boost/interprocess/managed_shared_memory.hpp> #include <boost/interprocess/containers/vector.hpp> #include <boost/interprocess/allocators/allocator.hpp> #include <boost/interprocess/sync/interprocess_mutex.hpp> #include <boost/interprocess/sync/interprocess_condition.hpp> #include <boost/interprocess/sync/scoped_lock.hpp> #include <iostream> using namespace boost::interprocess; // 复用和生产者相同的类型定义 using ShmemAllocator = allocator<int, managed_shared_memory::segment_manager>; using MyVector = vector<int, ShmemAllocator>; struct SharedData { interprocess_mutex mutex; interprocess_condition cond; MyVector vec; SharedData(const ShmemAllocator& alloc) : vec(alloc) {} }; int main() { try { // 打开已存在的共享内存段 managed_shared_memory segment(open_only, "MySharedMemory"); // 查找共享内存中的SharedData实例 SharedData* shared_data = segment.find<SharedData>("SharedData").first; if (!shared_data) { std::cerr << "Failed to find SharedData in shared memory!" << std::endl; return 1; } // 消费者逻辑:等待条件变量,然后读取vector元素 for (int i = 0; i < 5; ++i) { scoped_lock<interprocess_mutex> lock(shared_data->mutex); // 等待直到vector中有元素(防止虚假唤醒,所以用while循环) while (shared_data->vec.empty()) { shared_data->cond.wait(lock); } // 取出最后一个元素 int val = shared_data->vec.back(); shared_data->vec.pop_back(); std::cout << "Consumer received: " << val << std::endl; } } catch (const interprocess_exception& e) { std::cerr << "Interprocess error: " << e.what() << std::endl; shared_memory_object::remove("MySharedMemory"); return 1; } return 0; }
关键细节说明
- 同步原语的位置:
interprocess_mutex和interprocess_condition必须放在共享内存中,这样所有进程都能看到同一个锁和条件变量,普通的std::mutex只能用于进程内线程同步,不能跨进程。 scoped_lock的使用:它会自动管理锁的生命周期,避免手动解锁时出现遗漏或异常导致的死锁。- 条件变量的等待循环:必须用
while循环检查条件,因为可能会出现虚假唤醒(条件变量在没有被通知的情况下也可能返回),循环能确保只有当条件满足时才继续执行。 - 共享内存清理:如果进程异常退出,共享内存不会自动清理,所以最好在程序退出时(包括异常情况下)调用
shared_memory_object::remove,或者在下次启动时先清理旧的共享内存。
内容的提问来源于stack exchange,提问作者user997112
相关产品推荐
相关产品推荐

