6

It may sound dummy but,Am sort of confused, I have gone through this question,when looking into it we both where in the same situation it seems, I have to make my map as static so it will be common to all instances that will be created in separate threads and I want to synchronize the functions that gonna act on my map, so i thought of making a std::mutex as static in my class like what was suggested as an answer in the given link.. in this case will there be any race-condition occur for acquiring and locking the mutex itself? is there any better way we can synchronize the functions on static map using mutex

Community
  • 1
  • 1
RaGa__M
  • 2,550
  • 1
  • 23
  • 44
  • 4
    Obviously you have to use a second mutex to protect the first mutex – Praetorian Aug 09 '16 at 21:18
  • 2
    (I'm kidding, a mutex that itself is susceptible to a data race would be worthless) – Praetorian Aug 09 '16 at 21:19
  • @Praetorian. To your first comment, I was about about to type WTF ...Haha – WhiZTiM Aug 09 '16 at 21:19
  • @ Praetorian, So the static mutex would be fine in this case? – RaGa__M Aug 09 '16 at 21:21
  • 1
    You're mostly safe. Though, you might want to make sure that your compiler's initialisation of statics is thread safe. In MSVC, it wasn't until *very* recently. See: [magic statics](https://msdn.microsoft.com/en-au/library/hh567368.aspx#concurrencytable). – Sean Cline Aug 09 '16 at 21:22
  • @ magic statics,oh that lead me to an another little twist how to initialize a static mutex? – RaGa__M Aug 09 '16 at 21:23
  • 1
    @SeanCline That only applies to function local static variables. The OP wants the mutex as a static data member. FallingFromBed: Provide a definition for the mutex in a single cpp file, as you would for any other static data member. – Praetorian Aug 09 '16 at 21:27
  • @FallingFromBed Just like any other function-local static, It gets initialized automatically the first time its used. The worry is just that if 2 threads call it for the first time, at the same time, then construction needs to be safe. Luckily, the C++11 standard says it's safe.You just might want to make sure your compiler follows that part of the standard. – Sean Cline Aug 09 '16 at 21:28
  • 1
    @Praetorian Ahh, if we're talking about a static data member, then OP can safely ignore everything I've said. – Sean Cline Aug 09 '16 at 21:30

2 Answers2

7

Does Making std::mutex as static creates race-condition for the mutex itself

No, a Mutex isn't vulnerable to race-conditions. And as for initializing it as static, you are safe.

$6.7: 4: Dynamic initialization of a block-scope variable with static storage duration ([basic.stc.static]) or thread storage duration ([basic.stc.thread]) is performed the first time control passes through its declaration; such a variable is considered initialized upon the completion of its initialization. If the initialization exits by throwing an exception, the initialization is not complete, so it will be tried again the next time control enters the declaration. If control enters the declaration concurrently while the variable is being initialized, the concurrent execution shall wait for completion of the initialization


You said:

i thought of making a std::mutex as static in my class like what was suggested as an answer in the given link.

Do that if you are trying to protect static class member variables as well. Otherwise, make it a mutable member. The fact that you said the map will be globally initialized as static is okay, since the mutex as a member variable, will follow suite.

class Map{
public:
    Map(...){}

    std::size_t size() const{
         std::lock_guard<std::mutex> lck(m_m);
         return m_size;
     }

     iterator add(....) {
         std::lock_guard<std::mutex> lck(m_m);
         ....
         return your_iterator;
     }

     ...etc

private:
    mutable std::mutex m_m; //FREE ADVICE: Use a std::recursive_mutex instead
    ...others
};

Now:

//Somewhere at global scope:

Map mp(... ...);

// NOTES
// 1. `mp` will be initialized in a thread safe way by the runtime. 
// 2. Since you've protected all Read or Write member functions of the class `Map`,
//    you are safe to call it from any function and from any thread
WhiZTiM
  • 21,207
  • 4
  • 43
  • 68
3

No.

Mutexes (and other synchronisation primitives) are implemented using support from the operating system. That's the only way that they can do their job.

A direct corollorary of their ability to perform this job is that they are themselves not prone to race conditions — locking and unlocking operations on mutexes are atomic.

Otherwise, they wouldn't be much use! Every time you used a mutex, you'd have to protect it with another mutex, then protect that mutex with another mutex, and so on and so forth until you had an infinite number of mutexes, none of them actually achieving anything of any use at all. :)

The std::mutex object having static storage duration doesn't change this in any way. Presumably you were thinking of function-static variables (that, assuming they're not already immune to race conditions, must be synchronised because they may be accessed concurrently by different threads; but still, ideally you wouldn't use them at all because they make functions not be re-entrant).

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055