5

Consider this class:

#include <vector>

class A {
private:
    std::vector<int> m_vector;
public:
    void insertElement(int i) {
        m_vector.push_back(i);
    }
    const std::vector<int>& getVectorRef() const {
        return m_vector;
    }
};

Is the method getVectorRef thread safe?

Is it possible that during the return of getVectorRef another thread pops in and calls insertElementsuch that the member vector gets changed and the caller of getVectorRef gets a wrong const reference?

Have the two const qualifiers(one for the vector and the other for the method) no meaning in the context of thread safety?

Juergen
  • 3,489
  • 6
  • 35
  • 59
  • 2
    "Thread-safe" is such an overused word... it sometimes sounds like a magic bullet that you throw at some piece of code and that somehow makes concurrent programming easy. Yes, `getVectorRef` is "thread-safe", but what good is that information? You can still create tons of broken code with the given interface. You still need to understand what your code is doing! – Kerrek SB Sep 30 '13 at 13:21
  • 1
    You need to ensure that you sync access to a vector between threads, see http://stackoverflow.com/questions/4346742/stl-vector-and-thread-safety for more info. – HeatfanJohn Sep 30 '13 at 13:29

1 Answers1

4

The member function is thread safe, your interface isn't. In a class that is designed to be thread safe, you cannot yield references to the objects that you maintain, as if the user keeps the reference laying around she can use it while other operation is in place.

The member function is technically thread safe. The reference to the member is basically it's address, and that address cannot change. Whatever the other threads are doing, the reference will always refer to exactly the same object. But that is usually not your main concern. The real concern is what can the user do with the return of the function, and in this case the answer is basically nothing.

As soon as the user gets the reference, any access through it is going to cause a race condition when combined with any modification of that member in the original object. You cannot provide safe synchronization once you give references away, there is no way to make a thread safe interface out of a class that yields references.

If you need to make access thread safe, you can opt to either copy the value (within a critical section) or provide more fine grained functions that will handle the higher level requests from the user.

I'd recommend C++ concurrency in action by Anthony Williams for some of the discussions on how to make an interface thread safe.

BenMorel
  • 34,448
  • 50
  • 182
  • 322
David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489