这个练习线程安全吗?

时间:2013-11-27 05:39:38

标签: c++ thread-safety

假设我有一个这样的类..这只是一个抽象代码

class foo
{
public:
  int a;
  static foo* pfoo;
  foo()
  {
    pfoo = this;
  }
  fooCar* pFooCar;
  void someMethod();
}

现在其他一些课可能会这样做

foo::pfoo->someMethod();  

foo::pfoo->a = 14;

这种做法是否正确?

我应该将类的静态变量设为private并将静态变量的getter包装在互斥锁中吗?

像这样的东西

class foo
{
private:
static foo* pfoo;
public:
  int a;
  foo()
  {
    pfoo = this;
  }
  static foo* getFoo()
  {
      lock mutex..
      return pfoo
      unlock mutex..
  }
  fooCar* pFooCar;
  void someMethod();
}

还有其他建议吗?

4 个答案:

答案 0 :(得分:1)

首先,你的静态pfoo基本上只是单身模式,所以你可以用{Meyers singleton'替换pfoo这个东西,这是安全的(如果你想改变它)之后指针不适用):

class foo {
public:
    static foo* getFoo() {
        static foo singleton;
        return &singleton;
    }
};

但是,在收到指针后执行的任何都不能保证线程安全。但这一切都取决于你需要从代码中得到什么。根据应用程序的不同,线程安全会改变 lot ,尤其是读者和作者的数量。

现在,如果您只想让一个线程同时访问foo个成员,那么您可以只使用一个互斥锁:

class foo {
std::mutex fooMutex;
int bar;
public:
    static foo* getFoo() {
        static foo singleton;
        return &singleton;
    }

    void setBar(int newBar) {
        std::lock_guard guard(fooMutex); //This goes in every function that modifies the data.
        bar = newBar;
    }

    int getBar() {
        std::lock_guard guard(fooMutex); //If simultaneous readers are allowed then remove this
        return bar;
    }
};

这完全取决于您的使用案例。这只是最简单,最天真,效率最低的方法。如果您需要根据其当前值更改bar的值,则此操作无效。

答案 1 :(得分:0)

取决于您的设计要求。如果有相同类的对象在线程上处理某些共享数据,那么您需要显式处理同步线程对共享数据的访问。

在这种情况下,通过带锁的getter和setter公开成员变量是正确的。

答案 2 :(得分:0)

没有。静态变量初始化本身不是线程安全的。在一般情况下,在访问共享变量时应始终使用互斥锁/自旋锁。这不是原子的。

答案 3 :(得分:0)

不,你需要在一个原子步骤中将赋值包装到静态成员中;例如,临界区,互斥,InterlockedExchangePointer。虽然看起来这么简单的任务应该是线程安全的,但事实并非如此;即,赋值不是本机原子,可能会将部分分配的多字节变量暴露给另一个线程。

编辑:根据操作请求采样并删除令人困惑的段落

当然,您需要在使用互斥锁之前设置互斥锁

 foo()
  {
    pthread_mutex_lock (&mutex);
    pfoo = this;
    pthread_mutex_unlock (&mutex);
  }


  static foo* getFoo()
  {
      foo *retval;
      pthread_mutex_lock (&mutex);
      retval = pfoo;
      pthread_mutex_unlock (&mutex);
      return retval;
  }