2012-03-24 5 views
1

私が書いているマルチスレッドアプリケーションの問題については困惑しています。簡単に言うと、メインスレッドは、ファイルオブジェクトのリスト(ベクトル)を取得し、タイムスタンプをチェックし、変更されたファイルを別のベクターに渡すホットロードスレッドを開始します。マルチスレッドアプリケーションでのベクトルの使用

問題は、チェックする必要があるファイルの一覧に新しいファイルを追加しようとしたときに発生します。ホットロードスレッドは、リスト内のファイルの変更を継続的にチェックしています。反復処理中にスコープ付きロックでmutexをロック/ロック解除します。同様に、メインスレッドがaddItems()関数を呼び出すと、同じmutexが同様にロックされ、新しいファイルが追加されます。

私が読んだ情報によれば、これは適切なロックが与えられていればうまくいくはずですが、動作しますが、結果として非常に大きな減速が発生します。それは私がリストにも、一つのファイルを追加した場合、スレッドはますますロックになっているかのように...、、、

継続的に遅くなるプログラムですコード:

void MyThread::addItems(ItemList newItems) 
{ 

    ScopedLock<Mutex> lock(itemMutex_); 


    for (ItemList::iterator it = newItems.begin(); it != newItems.end(); ++it) 
    { 
     if (... test condition on (*it) ...) 
      items_.push_back((*it)); 
    } 
}; 

void MyThread::run() 
{ 
    _done = false; 
    do 
    { 
     YieldCurrentThread(); 

     if (!isEmpty_) 
     { 
      ScopedLock<Mutex> lock(itemMutex_); 
      for (ItemList::iterator it = items_.begin(); it != items_.end(); ++it) 
      { 
       if (... test condition on (*it) ...) 
        updatedItems_.push_back((*it)); 
      } 
     } 
    } 
} 

実行()関数のもちろん、item_eベクトルを繰り返し、addItems()関数を呼び出して別のスレッドから項目をベクトルに挿入します。 1つのスレッドだけがaddItems()を呼び出します。

それは難しいことはできませんが、私はまだ試していない解決策を示唆してそこに何かを見ていないよ...

EDIT:

  1. 思い出し以下のコメント私がaddItems()を呼び出さなければ、run()関数はアプリのパフォーマンスに大きな影響を与えていないように見えます。
+0

書かれているように、updatedItems_は常にitems_から同じ項目を追加するように見えます。 –

+0

addItemsメソッドがitemsパラメーターを使用していません。あなたはitems_の代わりにそれを繰り返すつもりでしたか? –

+0

申し訳ありませんが、読みやすいようにコードを編集しました。 addItems()関数で、私はタイプミスをしました。彼らは修正されました。更新された項目に関しては、ファイルのタイムスタンプが最後にチェックされてから変更されたかどうかを示す条件テストがあります。そうであれば、それは更新リストにプッシュされ、その後メインスレッドに戻され、クリアされます。 –

答えて

2

どのプラットフォームを使用していますか?変更されたファイルを監視しようとしている場合は、それを効率的に実行するためのオペレーティングシステムの機能があります。 Linuxではinotifyされるでしょう。 Windowsの場合、これは良い記事のようです:http://qualapps.blogspot.co.uk/2010/05/understanding-readdirectorychangesw.html

+0

Windowsを使用しています。 OS固有の解決策を避けようとしていますが、この場合は強制されることがあります。ポインタありがとう。 –

+0

確かに。 Windows上で解決しようとしているように見える問題には、デバッグされた解決策がいくつかあります。あなたの問題は基本的にミューテックスやベクトルではなく、あなたがやっている実際の処理で(おそらくやる必要はない)です。 –

+0

良い点。私はオリジナルの投稿を編集してそれに対処しました(私があなたが意味するものを理解すれば)、しかし私は間違いなく他の解決策も見ていきます。 –

1

あなたのロックはロックされていない時間がほとんどありません。 YieldCurrentThreadの実装方法によっては、遅延が非常に短くなることが予想されます。あなたのリストに多くのものがあれば、ベクトルにデータを追加するまでに平均でより長い時間が待つ必要があります。あなたのメインスレッドが多くの時間をaddItemsと呼んでいるなら、私は間違いなくいくつかの減速を期待しています。

for (;;) 
{ 
    ItemList snapshot; 
    if (!isEmpty_) 
    { 
     ScopedLock<Mutex> lock(itemMutex_); 
     snapshot = items_; 
    } 
    ItemList updated; 
    for (ItemList::iterator it = snapshot.begin(); it != snapshot.end(); ++it) 
    { 
     if (... test condition on (*it) ...) 
      updated.push_back((*it)); 
    } 
    if (!updated.empty()) 
    { 
     ScopedLock<Mutex> lock(itemMutex_); 
     updatedList_ = updated; 
    } 
} 

ここでの考え方は、重い処理を取り、ミューテックスの下からそれを移動することです:あなたが試みることができ

ことの一つは、このようになります糸ループです。もちろん、あなたの実際のボトルネックがロックの競合である場合、これは実際には何かをスピードアップします。問題が単なる多くのファイルのチェックに時間がかかる場合は、複数のスレッドと無関係です。

+0

私はめったにファイルを追加していません。ファイルを1つでも追加すると、アプリケーションのカスケード・スローダウンが開始されます。制御がアプリケーションに戻るまでに要する時間は大幅に増加し、終了することなく継続します。反復的なプロセスが何をしているのかは理解できません。それ以外の場合は、良い最適化のために+1してください! –

+0

他に何も触れていないのですか? 'updatedList_'を読み込むコードはどうですか?あなたが頻繁にそれをポーリングしているなら、あなたは繰り返しmutexをロックしています。そして今あなたのメインスレッドとバックグラウンドスレッドが互いに戦っています。 –

+0

実際には、updateList_を別のリソースと見なしているので、私は別のミューテックスを持っています。私のテストはaddItems()だけであったので、ここから除外しました。したがって、この場合、リソースがこのスレッド外でアクセスされる唯一の場所はaddItems()です。 –

関連する問題