简体   繁体   English

C++关联容器(unordered_map)从多个线程同时查找并插入同一个key

[英]C++ associative container (unordered_map) find and insert the same key at the same time from multiple threads

I am aware of other similar questions regarding find and insert at the same time, my question is specific to find and insert the SAME KEY at the same time.我知道关于同时查找和插入的其他类似问题,我的问题是特定于同时查找和插入 SAME KEY 的。

Per c++ 14 standard for containers requirements 23.2.5 "15. The insert and emplace members shall not affect the validity of iterators if (N+n) < z * B, where N is the number of elements in the container prior to the insert operation, n is the number of elements inserted, B is the container's bucket count, and z is the container's maximum load factor.".根据容器要求 23.2.5 的 c++ 14 标准“15. 如果 (N+n) < z * B,插入和 emplace 成员不应影响迭代器的有效性,其中 N 是插入之前容器中的元素数操作,n 是插入的元素数,B 是容器的桶数,z 是容器的最大负载因子。”。

According to this requirement, if I use unordered_map's reserve method, to pre-allocate buckets, this should take care of most racing conditions.根据这个要求,如果我使用 unordered_map 的保留方法来预先分配桶,这应该可以解决大多数赛车情况。 But what if you insert and find the SAME KEY at the same time from multiple threads?但是,如果您同时从多个线程插入并找到 SAME KEY 呢?

Update: what I really mean is that will find read garbage when inserting at the same time?更新:我真正的意思是同时插入时会发现读取垃圾?

I took some time to read the gcc implementation.我花了一些时间阅读 gcc 实现。

  1. If one thread insert using如果一个螺纹插入使用

    unordered_map mp; unordered_map mp; mp[key] = value; mp[key] = 值;

    while one thread read using: auto it = mp.find(key);而一个线程读取使用: auto it = mp.find(key); // then use it to access the key-value pair // 然后用它来访问键值对

    Then yes, using iterator returned by find() may get garbage, because this is what happened during mp[key] = value:那么是的,使用 find() 返回的迭代器可能会得到垃圾,因为这是在 mp[key] = value 期间发生的事情:

    1. operator[] dynamically create a node containing (empty_value) operator[] 动态创建一个包含 (empty_value) 的节点
    2. bucket pointers point to the newly created (empty_value) node.存储桶指针指向新创建的 (empty_value) 节点。
    3. the "=" then put "value" in the newly created node. “=”然后将“值”放入新创建的节点中。

    find(key) can read garbage after step 2 and before step 3 finishes. find(key) 可以在第 2 步之后和第 3 步完成之前读取垃圾。

  2. If we use unordered_map::insert, then it will be different, because what happened is:如果我们使用unordered_map::insert,那么它会有所不同,因为发生的事情是:

    1. Node containing (value) is dynamically created.包含(值)的节点是动态创建的。
    2. bucket pointer points to the newly created node.桶指针指向新创建的节点。

So when using find(key), either unordered_map cannot find the key-value pair, or the key-value pair has been fully created.所以在使用find(key)时,要么unordered_map找不到键值对,要么键值对已经完全创建。

This is my understanding to the implementation.这是我对实现的理解。 please correct me if I am wrong.如果我错了,请纠正我。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM