2009-06-09 19 views
1

スレッドの状況について質問があります。スレッド同期に関する質問

私は3つのスレッドがあるとします。プロデューサ、ヘルパー、コンシューマです。 プロデューサスレッドは実行状態(他の2つは待機状態)にあり、実行されたときには呼び出しが呼び出されますが、消費者ではないヘルパースレッドのみを呼び出さなければならない問題は、リソースを解放した後ヘルパースレッドのみでフェッチされ、次にコンシューマスレッドによってフェッチされます。あなたが持っている可能性があり、事前

+0

いくつかの条件(マルチプロセッサシステムや進行中のデータなど)では、複数のスレッドが実行状態になる可能性があることに注意してください。 – Adriaan

答えて

1

おかげで、例えば、2つのミューテックス(または使用しているものは何でも):生産者と消費者のためのプロデューサーとヘルパーのための1つ、およびその他の

Producer: 
    //lock helper 
    while true 
    { 
    //lock consumer 
    //do stuff 
    //release and invoke helper 
    //wait for helper to release 
    //lock helper again 
    //unlock consumer 
    //wait consumer 
    } 

他の人だけ通常はロックとアンロックを行います。

もう1つの考えられる方法は、プロデューサ/ヘルパー、およびその他のヘルパー/コンシューマにmutexを使用することです。他の2つのスレッド間でこのヘルパースレッドタスクを配布することもできます。詳細を教えてください。

+0

'mutex'を 'event'または 'signal'に変更してください。これは良い提案です。セマフォが通知されるのを待つのは、スレッド間の待機状態を設定する典型的な方法です。共有データのスレッドセーフを保証するものではありませんが、それは別の問題です。 – Kieveli

1

ヘルパースレッドは、実際にはコンシューマ/プロデューサスレッド自体です。あなたが他の消費者がプロデューサーの結果を取るように、ヘルパーのためのいくつかのコードを書いてください。それが完了したら、他のプロデューサのためのヘルパーのコードを書いて、コンシューマスレッドに接続します。

2

あなたは時々別のスレッドを持つことが解決策よりも問題であると考えましたか?

あなた本当には、おそらく簡単な解決策は、最初のスレッドが順番に操作を行うように、第2のスレッドを破棄し、コードを構造化することで、1つのスレッドで操作が別のスレッドで事業を厳密にシリアライズされたようにしたい場合希望。

これは必ずしも可能ではない可能性がありますが、頭に浮かべることです。

+0

+1質問が物事を並行ではなく連続して行う必要があるように見えるためです。その場合、スレッドはちょうど過度のものであり、釘を探しているハンマーです。 – mmr

+0

良い洞察力 - 問題は、手続き型プログラマがマルチスレッド化を始めていて、彼のソフトウェアを複数のスレッドでシリアルに実行するように設計していることです。面白い。 – Kieveli

1

キューを使用して、周囲のロックでこれを手助けすることができます。 プロデューサは何かに作用し、それを生成してヘルパーキューに配置します。 ヘルパーはそれを受け取り、それと何かを行い、コンシューマキューに配置します。 コンシューマーはそれを消費し、消費し続けます。このような

何か:

Queue<MyDataType> helperQ, consumerQ; 
object hqLock = new object(); 
object cqLock = new object(); 

// producer thread 
private void ProducerThreadFunc() 
{ 
    while(true) 
    { 
     MyDataType data = ProduceNewData(); 
     lock(hqLock) 
     { 
      helperQ.Enqueue(data); 
     } 
    } 
} 

// helper thread 
private void HelperThreadFunc() 
{ 
    while(true) 
    {   
     MyDataType data; 
     lock(hqLock) 
     { 
      data = helperQ.Dequeue(); 
     } 

     data = HelpData(data); 
     lock(cqLock) 
     { 
      consumerQ.Enqueue(data); 
     } 
    } 
} 

// consumer thread 
private void ConsumerThreadFunc() 
{ 
    while(true) 
    {   
     MyDataType data; 
     lock(cqLock) 
     { 
      data = consumerQ.Dequeue(); 
     }    
     Consume(data);    
    } 
} 

注:必ず使用可能にするには、この例にさらにロジックを追加する必要があります。それがそのまま動作することを期待しないでください。主に、あるスレッドのシグナルを使用して、そのキュー内でデータが利用可能であることを知らせます(最悪の場合、0より大きいかどうかを確認するためにキューのサイズをポーリングします。信号はよりクリーンでより効率的です)。

このアプローチでは、異なる速度でデータを処理できるようになります(メモリの問題が発生する可能性があります)。