multithreading - 使用互锁增量来增量STL映射的value字段。它是线程安全的吗?

标签 multithreading map stl thread-safety interlocked-increment

我有这样定义的 map 。

typedef std::map< tstring, unsigned int >  ErrorToCount_T;
ErrorToCount_T m_ErrorToSuppress;

我正在这样使用。
ErrorToCount_T::iterator itr = m_ErrorToSuppress.find( val );
if( itr != m_ErrorToSuppress.end())
{
    if( (itr->second) % m_LogFreq == 0)
        //Do something
    else
        //Do something else
    InterlockedIncrement( &itr->second);
}

我看到了this,并且我知道find是线程安全的。但是我在想InterlockedIncrement(&itr-> second)也将是线程安全的吗?上面的代码线程是否安全。
在多线程环境中,此映射中绝对没有插入。

最佳答案

如果两个线程使用相同的键(即val)执行代码,则以下列表中标记为(1)(2)的表达式可能会同时执行:

if( (itr->second) % m_LogFreq == 0) // (1)
    //Do something
else
    //Do something else
InterlockedIncrement( &itr->second); // (2)

(1)表达式中,将读取存储位置itr->second,在(2)表达式中将其写入。这就是所谓的数据争用,而C++ 11标准指出,如果程序的行为包含数据争用,则其行为是不确定的。

只要您的编译器供应商没有为您提供有关内存模型的其他保证,您就必须使用不会引起数据争用的操作。使用C++ 11,它可能如下所示:
using ErrorToCount = std::map<tstring, std::atomic<unsigned int>>;
ErrorToCount errorToSuppress;

ErrorToCount::iterator itr = errorToSuppress.find( val );
if( itr != errorToSuppress.end()) {
    if (itr->second.load(std::memory_order_seq_cst) % m_LogFreq == 0)
        //Do something
    else
        //Do something else
    itr->second.fetch_add(1, std::memory_order_seq_cst);
}

关于multithreading - 使用互锁增量来增量STL映射的value字段。它是线程安全的吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24121087/

相关文章:

c# - 当我调用 NavigationService.Navigate() 时,Windows Phone 应用程序调用 MapUri() 两次

python - 奇怪的线程行为

java - 需要对 Jar PathFinder 示例中发生的丢失通知进行解释

c++ - 并发写入 vector<bool>

c# - Silverlight - 是否可以在后台线程上创建 UI 元素?

hadoop - 有什么办法可以控制输入减少 map 减少

C++函数映射实现

c++ - STL 迭代器 : Assertion Error

c++ - STL中struct类型的迭代队列

c++ - 迭代 vector 和其他 STL 容器的样式之间的区别