2012-02-16 157 views
6

我正在使用std :: vector作为多线程应用程序中的共享数据。我封装螺纹的类中,例如,std ::向量,线程安全,多线程

class ABC { 
public: 
    double a, b, c; 
}; 

boost::mutex mutex1; 

class XYZ { 
public: 
    XYZ(vector<ABC> & pVector) { 
     ptrVector = &pVector; 
     m_thread = boost::thread(&XYZ::Start, this); 
    } 
    ~XYZ() {} 
    void Start(); 
public: 
    vector<ABC> * ptrVector; 
    boost::thread m_thread; 
};  

void XYZ::Start() { 
    try { 
     while(1) { 
      boost::this_thread::interruption_point(); 
      for (unsigned int i=0; i<ptrVector->size(); i++) { 
       { 
        boost::mutex::scoped_lock lock(mutex1); 
        ptrVector->at(i).a = double(rand())/10000; 
        ptrVector->at(i).b = double(rand())/10000; 
        ptrVector->at(i).c = double(rand())/10000; 
       } 
      } 
     } 
    } 
    catch(boost::thread_interrupted) {} 
    catch(std::exception) {} 
} 

当我关闭应用程序,有时,在调试,会有2个错误消息,有时会有任何错误消息。我经常听到人们在谈论std :: vector不是线程安全的,这是这种情况之一吗?我正在使用Visual Studio 2008,boost线程,矢量的大小是固定的。任何人都可以提供一些关于如何在多线程应用程序中使用std :: vector的建议。在ETP.exe 0x7688b9bc

  1. 第一次机会异常:微软C++ 例外:的std :: out_of_range内存位置0x02d8f7bc ..在ETP.exe 0x00e916e0
  2. 第一次机会异常:0000005:访问 违规阅读地点0x00000008。
  3. 第二次机会断言失败:文件C:\ Program Files文件 (x86)的\微软的Visual Studio 9.0 \ VC \包括\载体,线路二 机会断言失败:文件C:\ Program Files文件(x86)的\微软 视觉studio 9.0 \ vc \ include \ vector98

谢谢。

+0

矢量不是线程安全的,如果你尝试从不同的线程同时那么它将打破写入。尽管你正在锁定它,并且没有其他代码来查看你是如何使用它的,但是不可能知道可能发生了什么问题。这个特殊的代码本身看起来很好。 – Jarryd 2012-02-16 04:06:13

+0

除了线程安全之外,您可能还需要考虑线程访问向量的顺序,如果一个线程正在读取向量,那么您应该确保另一个线程已经写入向量或至少您的代码应该处理矢量尚未写入的条件。 – 2012-02-16 04:13:53

+0

@Jarryd你是仪式,在这段代码中,似乎他使用互斥锁来锁定向量,如果他这样做,那么它不应该引起问题,因为我们需要去完成代码的细节 – 2012-02-16 04:14:44

回答

22

其实,它绝对是毫无意义的状态X是或不是线程安全的!你需要符合什么样的用途。例如,几乎任何类在某种线程中以某种方式使用并在另一线程中被销毁时都不会“线程安全”。

也就是说,std::vector<T>不是线程安全的,独立于它重复的频率是错误。但是,似乎大多数人既不理解也不欣赏给出的线程安全保证。 std::vector<T>在以下意义上是线程安全的:

  • 您可以同时从多个线程中读取矢量对象。
  • 如果有一个线程更改矢量对象,则不应该有并发读者或写者。
  • 访问矢量对象不会干扰其他矢量对象。

这适用于向量结构本身。对包含对象的访问必须遵守施加于其上的任何规则。这些显然不是许多人想到的线程安全保证,但更强大的东西不能用于容器接口。

+0

感谢您的意见。现在我对此更加清楚了。 – 2607 2012-02-21 04:29:37

+0

对不起,但完全不同意你的看法,线程安全是一个已知的定义,指出实现应该保证并发(线程)保护它的共享区域以避免冲突,这意味着一个类是线程安全的或者不是,说明它取决于使用意味着它不是线程安全!,这怎么能是正确的答案? – Cross 2017-02-21 18:50:33

+0

您可以同时从多个线程读取。是的 - 只要在上次修改后发布了释放内存屏障,并且在所有读取线程上都出现了匹配的获取内存屏障...... – Persixty 2017-05-04 10:38:40

4

您可以先致电ptrVector->size(),而不要先将其锁定。这很容易成为你问题的原因。确保在读取或写入之前锁定您的矢量。

+1

他说大小矢量是固定的,所以不应该引起问题。但是,由于我们没有更多的代码,我们不知道他是否在不知道的情况下以线程不安全的方式添加它。 – Jarryd 2012-02-16 05:16:19