如何使C++映射::交换线程安全

How to make a C++ map::swap thread safe?

本文关键字:交换 安全 线程 映射 何使 C++      更新时间:2023-10-16

我需要交换一个std::映射来更新一些配置。这发生在一个线程中。

在另一个线程中,我需要读取该映射中的值(目前只有一个使用者线程)。

在生产者线程中,我目前有(伪代码):

pthread_mutex lock;
std::map<int, char> current_config;
std::map<int, char> new_config;
...
<Read into new config>
ScopeLock(lock);
current_config.swap(new_config);

在使用者线程中,我调用生产者线程中执行以下操作的访问器:

ScopeLock(lock)
return current_config;

这似乎会阻止消费者在交换过程中访问地图,但我想知道如果消费者正在使用地图,然后生产者需要交换地图会发生什么。

这根线安全吗?

我想我可以在两个线程中都做一个锁,但我试图避免要求消费者使用锁。

如果访问器通过引用返回,则代码是不安全的,因为使用者获得了引用,锁被释放,但生产者可能会进行另一次交换。

如果访问器按值返回,那么您的代码可能是安全的,因为您设置了锁并返回了一个副本,然后删除了锁。

我说"可能"是因为你的保护不够:我想你的生产者不仅在交换地图,而且还在初始化、填充和更新地图。因此,您需要为每个以任何方式修改映射的生产者函数设置锁。其他人,你的消费者可以阅读地图,认为它是安全的,而其他代码则会改变现有的位置。

此外,使用副本意味着您的消费者可能会使用过时的数据,从而使处理不那么并发

另一种选择是生产者和消费者使用共享映射,该映射嵌入到一个对象中,该对象旨在嵌入生产者和消费者对映射的线程安全访问。