0

我正在使用一个库,它使用多线程在事件发生时调用成员函数。库中的每个“处理程序”都有一个可以调用函数的线程MyClass::Process(const Signal& signal)。MyClass 引用了一个Catalog名为cat.

在里面Process我有以下代码:

Stats stats;//simple container struct to hold values

std:string id(signal.signalId());
//set values of stats here based on the values in signal

cat->onSignalUpdate(id, stats);

从库的文档中:

在单个 Handler 实例的范围内不可能同时调用两个用户回调。但是,不同通道的不同 Handler 实例没有相互链接,因此来自不同 Handler 实例的调用可能会并行发生。

目录有成员std::map<std::string, Stats> signal_map

代替Catalog::onSignalUpdate(const std::string& id, const Stats& stats)

std::map<std::string, Stats>::iterator it(signal_map.find(id));
if(it != signal_map.end())
{
    it->second = stats;
}

这在很多时候都有效,其中正确的 Id 被映射到适当的 Stats 结构。有时,在将处理程序 A 的 ID 分配给属于处理程序 B 的结构的情况下,我会遇到不正确的匹配。在我看来,该函数是被并行调用的。我的印象是,在线程中,对函数的调用虽然是并行完成的,但却是重复的。不是这种情况,还是在线程中通过引用传递值存在问题?

4

1 回答 1

2

std::map如果没有针对多个线程同时修改的某种形式的保护,您将无法从多个线程更新 a map。你需要一个互斥锁或类似的东西。特别是,如果id是“新的”,则映射中的底层数据结构(通常是“RB-tree”)将被更改。这不能从多个线程中完成。您也不能在修改树时访问树以“读取”它,因为树中的条目可能是“半更新”的(例如,下一个元素指向一个尚未正确填写的元素或一些这样的)。

于 2013-10-16T21:36:05.413 回答