问题
I have a static map as a member variable of my class. Do we need to have static lock when we have to access this map?
回答1:
If your std::map
instance is declared class static, then your lock needs to be class static too.
Consider two threads working against separate objects using the map when the lock is a non static member but the map is.
- Object 1 locks the local lock and starts manipulating the shared map.
- Object 2 locks its local lock (it's a separate lock, remember) and starts manipulating the shared map.
- Boom/crash/burn
If the lock is class static, the two objects will share the lock, and the above scenario will work well, only one thread can lock at a time.
There are of course other ways to share a lock without using static
, but that does not seem to be what you're asking.
回答2:
You need exactly one mutex
per object that has to be used in a synchronized way. Having multiple mutexes for one object will lead to race conditions as shown by the example Joachim Isaksson has given in his answer.
There are different ways of static
variables:
class static (wich is probably what you mean):
class X { static map<A,B> mMap; };
You have exactly one object system-wide. In this case, the mutex for the map should be class static as well and should be locked whenever the map is used in a way that needs to be synchronized. Keep in mind, that initialization of class static members is not threadsafe.
function local static:
class X { void foo() { static map<A,B> theMap{ /* ... */ }; } };
You have one object system-wide, regardless of wether
foo
itself is class static or not. Initialization of that object is guaranteed to be threadsafe. You need exactly one mutex system-wide as well. That mutex should be either static insidefoo
or class static or global. In the latter two cases, it must be locked before every call offoo
. That is the classic usecase of the Meyers singleton:class X { static mutex mapMutex; static map<A,B>& getMap() { static map<A,B> theMap{ /* ... */ }; return theMap; } void useMap() { lock myLock(mutex); getMap()[a] = b; } };
translation unit static ("global static")
static map<A,B> gMap; class X { /* ... */ };
You have one object inside every translation unit that has such a declaration, i.e. if it is inside a .cpp, you get one object. If it is inside a header, you get one object for every translation unit that includes that header. The mutex for that object should be translation unit static as well, as you need as many mutexes as there are objects. However, I would not recommend using that kind of static variables in a multithreaded environment.
回答3:
First of all you should consider reading smth on static
(Try this, maybe). That's because meaning of static
depends on context.
But that's probably a complication, I believe you have something like this:
class A {
private:
static std::map....
public:
void doSomethingWithMap() {
//lock mutex
//some action with map
//unlock mutex
}
}
If that's the case, then you might want to have your mutex as a member of this class. That's the point - it depends on the scope you need. If you need to lock globally across all the objects of this class - you should consider using static class member, if you want to have lock per object - you should settle with just a class member.
回答4:
No, generally you don't need a static lock.
来源:https://stackoverflow.com/questions/17357909/do-we-need-to-have-static-lock-for-static-member-variable-of-the-class-in-c