0

我有一个静态地图作为我班级的成员变量。当我们必须访问这个地图时,我们需要有静态锁吗?

4

4 回答 4

7

如果您的std::map实例被声明为类静态,那么您的锁也需要是类静态的。

当锁是非静态成员但映射是时,考虑使用映射处理单独对象的两个线程。

  • 对象 1 锁定本地锁并开始操作共享映射。
  • 对象 2 锁定其本地锁(记住,它是一个单独的锁)并开始操作共享映射。
  • 繁荣/崩溃/燃烧

如果锁是类静态的,两个对象会共享锁,上面的场景也可以正常工作,一次只能有一个线程加锁。

当然还有其他方法可以在不使用的情况下共享锁static,但这似乎不是你要问的。

于 2013-06-28T05:55:51.157 回答
0

每个对象都需要一个mutex必须以同步方式使用的对象。一个对象有多个互斥体将导致竞争条件,如 Joachim Isaksson 在他的回答中给出的示例所示。

static变量有多种方式:

  1. 类静态(这可能是你的意思):

    class X {
      static map<A,B> mMap;
    };
    

    您在系统范围内只有一个对象。在这种情况下,映射的互斥锁也应该是类静态的,并且每当映射以需要同步的方式使用时都应该被锁定。请记住,类静态成员的初始化不是线程安全的。

  2. 函数局部静态:

     class X {
       void foo() {
         static map<A,B> theMap{ /* ... */ };
       }
     };
    

    你有一个系统范围的对象,不管foo它本身是否是静态类。该对象的初始化保证是线程安全的。您还需要一个系统范围内的互斥锁。该互斥锁应该是内部的静态foo或类静态或全局的。在后两种情况下,必须在每次调用foo. 这是 Meyers 单例的经典用例:

     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;
       }
     };
    
  3. 翻译单元静态(“全局静态”)

     static map<A,B> gMap;
    
     class X { /* ... */ };
    

    您在每个具有此类声明的翻译单元内都有一个对象,即如果它在.cpp 内,您将获得一个对象。如果它位于标头内,您会为每个包含该标头的翻译单元获得一个对象。该对象的互斥锁也应该是静态翻译单元,因为您需要与对象一样多的互斥锁。但是,我不建议在多线程环境中使用这种静态变量。

于 2013-06-28T06:54:51.567 回答
-1

首先,您应该考虑阅读static(也许试试这个)。那是因为含义static取决于上下文。

但这可能是一个并发症,我相信你有这样的事情:

class A {
    private:
        static std::map....

    public:
        void doSomethingWithMap() {
            //lock mutex

            //some action with map

            //unlock mutex
        }
}

如果是这种情况,那么您可能希望将互斥锁作为此类的成员。这就是重点——这取决于您需要的范围。如果你需要在这个类的所有对象上全局锁定——你应该考虑使用静态类成员,如果你想锁定每个对象——你应该只使用一个类成员。

于 2013-06-28T06:06:51.377 回答
-2

不,通常您不需要静态锁。

于 2013-06-28T05:42:22.153 回答