2

I have a map like this

map<string,A>

Now when I am iterating through the map from thread I, thread II is inserting something on to it. Will this insertion affect the reading ?

πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
Ram
  • 389
  • 4
  • 13
  • Yes. In a word. You might get away with a std::list because insert doesn't invalidate iterators, but I can still see a chance for trouble. Look up thread safe queues? – doctorlove Jul 13 '16 at 09:44
  • @doctorlove std::map doesn't invalidate any more iterators than std::list does. Neither of them are thread safe. – eerorika Jul 13 '16 at 12:35

2 Answers2

7

Yes, the insert can affect the reading. The standard does not provide a thread safety guarantee. There is a race condition, and it leads to undefined behaviour.

eerorika
  • 232,697
  • 12
  • 197
  • 326
  • A race condition **always** leads to undefined behavior. – Pete Becker Jul 13 '16 at 11:41
  • How does the insertion affect the reading? Per [this](http://stackoverflow.com/a/6442829/4342498) insertion does not affect any other element. – NathanOliver Jul 13 '16 at 11:42
  • @NathanOliver although the answer doesn't explicitly say so, it is describing the *post conditions* of the operations. Technically, post conditions do not apply until the operation has returned. The problem isn't merely the validity of references. The `map` may be in an inconsistent state during the insertion. – eerorika Jul 13 '16 at 11:53
  • @user2079303 But if the user is iterating through the map then it should not matter since whatever iterator they have will always have a valid element. The writer is not changing the elements the iterator points to(at least that is what I think from the OP's limited explanation). – NathanOliver Jul 13 '16 at 12:00
  • @NathanOliver since the reader could be incrementing the iterator while the map is inconsistent, no it is not guaranteed to always have a valid element. Operations on an inconsistent map simply have no well defined behaviour. – eerorika Jul 13 '16 at 12:21
1

Yes it will affect the reading. You need additional synchronization mechanism between those two threads. Read about std::mutex and std::unique_lock.

See example code below:

#include <map>
#include <string>
#include <mutex>
#include <memory>

class MapWithMutex
{
public:
    int readFromMap(const std::string& key)
    {
        std::unique_lock<std::mutex>(mtx);
        //add some check if elements exists
        return myMap[key];
    }
    void insertToMap(const std::string& key, int value)
    {
        //add check if element doesn't already exist
        std::unique_lock<std::mutex>(mtx);
        myMap[key] = value;
    }
private:
    std::map<std::string,int> myMap;
    std::mutex mtx;
};

int main() {
    MapWithMutex thSafeMap;
    //pass thSafeMap object to threads
    return 0;
}

Remember to make critical section as small as possible

paweldac
  • 1,144
  • 6
  • 11