简体   繁体   中英

c++17 another qeustion about threadsafe behavior through iterator

My need is just like below: One thread (named thread 1) just keeps inserting pairs into the common map. And the other thread (named thread 2) keeps getting the element at the begin position (no matter if it is still at the beginning while other thread insert an element at the begin position) and do some operation to the element and erase the iterator.

I know that STL is not threadsafe, but it is still a good container to use. So my method is every time thread 2 get the element, I make a copy of it and do my work, and protect insert/delete/begin/end by one mutex.

pseudocode like below under c++17

my_map {
    insert(value_type value){
        lock_guard(mutex)
        map.insert(value)
    }
    erase(iterator position){
        lock_guard(mutex)
        map.erase(position)
    }
    end(){
        lock_guard(mutex)
        map.end()
    }
    begin(){
        lock_guard(mutex)
        map.begin()
    }
}

thread 1:

while(1){
    sleep(1)
    my_map.insert(random())
}

thread 2:

while(!my_map.empty()){
    auto it = my_map.begin()
    auto k = it->first;
    auto v = it->second;
    work(k, v);
    my_map.erase(it);
}

螺纹图

What's the behavior if the sequence in the picture happens? That is to say, in the same "map" when in one thread "insert" happens, and in the other thread "copy with iterator" happens, will the "insert" disturb the iterator to make "copy" wrong or destroy the iterator to make iterator invalid at the "copy" time?

I was told it is threadsafe if I use copy of the map but not ok with the iterator, so it is correct? And how do I make the copy of one element in the map or some other STL containers to achieve threadsafe?

For std::map , insertion won't invalidate container iterators (or element references) , so it (and it->first and it-second ) in thread 2 shouldn't be affected by thread 1's my_map.insert . (Note: this is entirely due to the standard behavior for containers, not the locks. Though the locks ensure my_map.insert(...) in thread 1 and my_map.begin() and my_map.erase(...) won't overlap, they don't affect the interaction of the insertion in thread 1 and accessing through the iterator in thread 2.)

As thread 1 doesn't operate on items from the map, there's nothing for thread 2's my_map.erase(...) to affect in that regard. Even if thread 1 did operate on an iterator or reference to an item from my_map , the erase would only invalidate erased elements.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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