我们是否需要在c ++中对类的静态成员变量进行静态锁定

时间:2013-06-28 05:39:24

标签: c++ locking

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

4 个答案:

答案 0 :(得分:4)

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

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

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

如果锁是静态类,则两个对象将共享锁,并且上述方案将运行良好,一次只能锁定一个线程。

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

答案 1 :(得分:0)

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

static变量有不同的方法:

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

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

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

  2. function local static:

     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中,则会得到一个对象。如果它位于标题内,则每个包含该标题的翻译单元都会获得一个对象。该对象的互斥锁也应该是转换单元静态,因为您需要与对象一样多的互斥锁。但是,我不建议在多线程环境中使用这种静态变量。

答案 2 :(得分:-1)

首先,您应该考虑在static上阅读smth(也许请尝试this)。那是因为static的含义取决于背景。

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

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

    public:
        void doSomethingWithMap() {
            //lock mutex

            //some action with map

            //unlock mutex
        }
}

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

答案 3 :(得分:-2)

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