同一对象的多个副本(C ++):线程安全吗?

时间:2012-06-22 17:10:07

标签: c++ multithreading

我有一个相当简单的问题,但答案似乎无法回避我。如果我有多个相同c ++类的对象,每个对象都在自己的线程中,我是否需要了解并发访问问题?或者对于单独的实例,事物是自动线程安全的吗?当然我会期待静态方法的问题,但是实例方法呢?

6 个答案:

答案 0 :(得分:2)

如果每个帖子中都有单独的对象,那么你就可以了。如果您在该类中有静态成员变量,则可能会遇到问题。

显然,如果您的线程函数正在访问全局或共享数据,这仅适用于所讨论的类对象的数据,那么通常的多线程问题将适用。

答案 1 :(得分:2)

这取决于。通常,类的一个实例将独立于其他实例上的操作。如果在单个线程中就是这种情况,那么多线程也是如此。

例如,考虑表示Point的值类型类。

class Point { 
public:
   int x, y, z 
};

一个线程中此类的实例不受另一个线程中不同实例上的操作的影响。

但是,类的实例可以与其他对象进行交互。如果两个实例可以与同一个对象进行交互,那么是的,您确实需要关注线程安全性。

答案 2 :(得分:1)

实例变量都是独立的。因此,如果实例方法仅使用实例和局部变量,则无需担心线程安全。

答案 3 :(得分:0)

只要来自一个对象的线程不调用另一个对象上的方法,就应该没有问题。

但如果您有递归方法并且正在获取方法中的互斥锁,那么您可能会遇到死锁。如果是这种情况,您将需要使用递归互斥锁。

答案 4 :(得分:0)

问题的根源在于如何在内存中布置对象。假设不涉及静态数据成员(很少见),每个对象独立于相同类型的其他对象,因为这样的对象(如内存中所示)仅由对象的多个数据成员组成。例如,假设类型定义

class Location {
  private:
    double latitude1;
    double longitude1;
  public:
    double latitude () const { return latitude1;  }
    double longitude() const { return longitude1; }
    Location(const double lat0, const double long0) {
      latitude1  = lat0;
      longitude1 = lon0;
    }
    // Calculate the Location at exactly the furthest
    // point on earth (implemented elsewhere).
    Location antipode();
};

假设该类型的单独对象在其他地方实例化为

Location my_loc(-100.0, 35.0);
const Location your_loc(15.0, 45.5);

然后,my_loc本身只包含内存中的一对双打(在这种情况下,堆栈上有一对连续的双打);而your_loc本身只包含一对双打。所以,你看,就数据而言,Location只不过是两个双精度的结构。

但是,你问:构造函数和antipode()等等是什么?答案是它们每个只存在一次 - 而且,就内存而言,它们并不直接与数据相关联。单独的编译器将数据与函数相关联。线程不关心。

如果你根据上述情况考虑到这一点,那么就会怀疑你所得到的答案将会落在你身上。

答案 5 :(得分:0)

您可以粗略地将C ++项目分为4类:

  • 只读:文字,常量,函数等...在代码执行过程中无法修改,因此本身可以安全地共享
  • 全局变量:命名空间范围内的全局变量,类的静态属性,函数中的本地静态等等......都可以修改,因此必须使用正确的多线程感知机制
  • 线程局部变量:以上所有变量,但标有thread_local存储限定符;见下一点
  • 实例变量:类或结构属性,函数局部变量,......使用本质上是安全的,只要它们没有明确共享

总而言之,您不必担心方法或功能,也可以自由地共享常量。

在中间范围内,请确保不要共享(甚至是无意中)本地变量,至少在没有确保正确同步访问的情况下是这样。

最后,要非常警惕全局。