2012-02-16 14 views
6

私はマルチスレッドアプリケーションで共有データとしてstd :: vectorを使用しています。私は、例えば、std :: thread、thread-safety、multi-threading

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) {} 
} 

Iは時々アプリケーション、を閉じると、デバッグ中に、は時々エラーメッセージが存在しないであろう2つのエラーメッセージが存在するであろう、クラス内のスレッドをカプセル化します。私はしばしば、std :: vectorがスレッドセーフではないという話を聞いたことがありますが、これはケースの1つですか?私はVisual Studio 2008を使用して、スレッドをブーストして、ベクトルのサイズが固定されています。誰もマルチスレッドアプリケーションでstd :: vectorを使用する方法についてアドバイスを提供することができますか? ETP.exeで0x7688b9bcで

  1. 初回例外:マイクロソフトC++ 例外:メモリ位置0x02d8f7bcでのstd :: out_of_range .. ETP.exeで0x00e916e0で
  2. 初回例外:0xc0000005で:アクセス 違反の読書場所は0x00000008です。
  3. セカンドチャンスアサーションが失敗しました:ファイルC:\プログラムファイル (のx86)をマイクロソフトのVisual Studio 9.0 \ VCの\ \ \ベクトルが含まれ、ラインセカンド チャンスアサーションは失敗しました:ファイルC:\プログラムファイル(x86の)をマイクロソフト のビジュアル\ studio 9.0 \ vc \ include \ vector98

ありがとうございます。

+0

ベクトルは、スレッドセーフではありません。あなたはそれをロックしています、そして、あなたがそれをどのように使用しているかを見るための他のコードなしで、何がうまくいかないかもしれないと言うことは不可能です。この特定のコードは、それだけで正常に見えます。 – Jarryd

+0

スレッドの安全性とは別に、スレッドがベクトルにアクセスする順序を考慮する必要もあります。あるスレッドがベクトルから読み込んでいる場合は、別のスレッドがそのベクトルの前にベクトルに書き込まれていることを確認する必要がありますコードは、ベクトルが書き込まれていない条件を処理する必要があります。 –

+0

@Jarrydあなたはこのコードで、mutexを使ってベクトルをロックしているようですが、もしそうなら、問題は起こらないはずです。詳細については、完全なコードを参照してください。 –

答えて

22

実際にはです。無意味な状態Xはスレッドセーフですか!あなたはどのような用途に使用する資格が必要です。たとえば、あるスレッドで何らかの形で使用され、別のスレッドで何らかの形で破棄されると、ほとんどのクラスは「スレッドセーフ」になりません。

つまり、std::vector<T>はスレッドセーフではなく、繰り返し回数に関係なく、が間違っていますです。しかし、ほとんどの人は、スレッドセーフティの保証を理解していないし、感謝していないようです。 std::vector<T>は、次の意味でスレッドセーフです。

  • 複数のスレッドから同時にベクトルオブジェクトを読み取ることができます。
  • ベクトルオブジェクトを変更するスレッドが1つある場合、並列リーダまたはライタは存在しないものとする。
  • ベクトルオブジェクトへのアクセスは、他のベクトルオブジェクトに干渉しません。

これはベクター構造そのものに適用されます。格納されたオブジェクトへのアクセスは、それらに課せられた規則に拘束されます。これらは明らかに多くの人が念頭に置いているスレッドセーフな保証ではありませんが、それ以上のものはコンテナインタフェースでは動作しません。

+0

アドバイスをいただきありがとうございます。今私にはもっとはっきりしています。 – 2607

+0

申し訳ありませんが、まったく同意しませんが、スレッドセーフとは、実装が競合を避けるために共用領域を保護することを保証する必要があることを示す既知の定義です。つまり、クラスはスレッドセーフであるかどうかを示します。それはスレッドセーフではないことを意味する使用法に依存します!これは正解でしょうか? – Cross

+0

複数のスレッドから同時に読み取ることができます。はい - それは最後の変更と一致するメモリの障壁がすべての読書スレッドで発生した後にリリースメモリの障壁が発生した限り... – Persixty

4

ptrVector->size()に電話をかけてください。これは簡単にあなたの問題の原因となる可能性があります。読み書きの前に必ずベクトルをロックしてください。

+1

彼は、ベクトルは固定されているので、問題は生じないはずです。しかし、コードが増えているわけではないので、スレッドなしで安全に追加するかどうかはわかりません。 – Jarryd

0

これを代わりに使用できますか?

concurrent_vector ...あなたはそれが壊れる異なるスレッドから同時にそれへの書き込みをしようとした場合、インテルスレッディング・ビルディング・ブロックから

https://software.intel.com/en-us/node/467758

関連する問題