使用互锁增量递增 STL 映射的值字段。它是线程安全的吗?



我有一个这样定义的映射。

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);
}

我看到了这个,我明白这个发现是线程安全的。但我在想,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);
}

相关内容

  • 没有找到相关文章

最新更新