【问题标题】:tbb concurrent hash maps: how to compare and settbb 并发哈希映射:如何比较和设置
【发布时间】:2013-03-03 12:51:51
【问题描述】:

我需要以 CAS 方式更新 TBB 提供的 concurrent_hash_map 中的内容。也就是说,如果键已经存在,我会查看与键对应的值并在原子操作中更新值(如果值同时由于另一个线程做同样的事情而发生变化,我的操作应该会失败)。

换句话说,我为插入方法提供了一个“预期值”,它仅在当前值与预期值匹配时才更新该值。

在 TBB 的 concurrent_hash_map 中是否有实现这一点的方法?

非常感谢。

【问题讨论】:

    标签: concurrency hashmap tbb


    【解决方案1】:

    给定类型 Key 和 T,下面的代码实现了目标,假设类型 T 是支持 tbb::atomic 的类型。

    class AtomicValue {
        mutable tbb::atomic<T> content;
    public:
        AtomicValue() {}
        AtomicValue( T value ) {content=value;}
        bool cas( T value, T comparand ) const {
            return content.compare_and_swap(value,comparand)==comparand;
        }
    };
    
    typedef tbb::concurrent_hash_map<Key,AtomicValue> table;
    
    bool update( table& x, Key key, T value, T comparand ) {
        table::const_accessor a;
        if( !x.insert(a,table::value_type(key,value) ) ) {
            // value is already there
            return a->second.cas(value,comparand);
        }
        return true;
    }
    

    棘手的部分是使用 const_accessor 进行更新。使用常规访问器将序列化更新。但是 const_accessor 允许多个线程同时访问同一个表条目。它被称为“const_accessor”,因为通常的用例涉及读取值。但是这里的代码使用 CAS 来仲裁更新。包装类“AtomicValue”允许对 const 对象执行 CAS。

    类似的解决方案应该适用于 tbb::concurrent_unordered_map,如果非阻塞是关键标准,这可能会更好,因为 concurrent_unordered_map 具有非阻塞实现。

    更好的是,如果您拥有最新的 TBB支持 constexpr 的 C++11 功能和默认/删除的成员函数的编译器,则以下内容应该可以工作:

     typedef tbb::concurrent_unordered_map<Key,tbb::atomic<T> > table;
    
    bool update( table& x, Key key, T value, T comparand ) {
        auto p = x.insert(table::value_type(key,value) );
        if( !p.second ) {
            // value is already there
            return p.first->second.compare_and_swap(value,comparand) == comparand;
        }
        return true;
    }
    

    当使用“g++ -std=c++0x”编译时,它适用于 gcc 4.7。

    【讨论】:

    • 这就是我要找的。非常感谢。
    • 如果表在插入失败和以下 CAS 之间调整大小/重新散列怎么办?更新的值不会被写入无效的内存位置吗?
    • concurrent_unordered_map 使用拆分顺序列表,而不是开放寻址。因此调整大小不会移动项目。有关拆分订单列表的详细信息,请参阅people.csail.mit.edu/shanir/publications/…——这是一个聪明的主意。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多