2012-02-13 9 views
0

誰かがこれを正しく設計するのを助けることができます。リソースがビジー状態の場合に限り、スレッドとワーカーキューを生成する

私のTCPコードでは、ワイヤに書き込もうとするSendMessage()関数があります。私は、多くの同時リクエストが発生した場合にプロデューサ/コンシューマモデルに移動するようにコールを設計しようとしていますが、(最大のパフォーマンスのために)同時リクエストがない場合は、シングルスレッドのままです。

スレッド間でロックを移動する方法がないため、これを競合条件なしに設計する方法には苦労しています。

私がこれまで持っていることは(擬似コード化された)のようなものです:

SendMessage(msg) { 

    if(Monitor.TryEnter(wirelock,200)) { 

     try{ 
      sendBytes(msg); 
     } 
     finally { 
      Monitor.Exit... 
     } 
    } 
    else { 

    _SomeThreadSafeQueue.add(msg) 

    Monitor.TryEnter(consumerlock,.. 

      Task.Factory.New(ConsumerThreadMethod.... 
    } 
} 


ConsumerThreadMethod() { 

    lock (wirelock) { 

     while(therearemessagesinthequeue) 

       sendBytes... 

    } 

} 

任意の明白な競合状態?

EDIT:最後のものに欠陥が見つかりました。これについてはどうですか?

SendMessage(msg) { 

    if(Monitor.TryEnter(wirelock)) { 

     try{ 
      sendBytes(msg); 
     } 
     finally { 
      Monitor.Exit... 
     } 
    } 
    else { 

     _SomeThreadSafeQueue.add(msg) 

     if (Interlocked.Increment(ref _threadcounter) == 1) 
     { 
      Task.Factory.StartNew(() => ConsumerThreadMethod()); 

     } 
     else 
     { 
      Interlocked.Decrement(ref _threadcounter); 

     }  
    } 
} 


ConsumerThreadMethod() { 

    while(therearemessagesinthequeue) 
      lock (wirelock) { 
       sendBytes... 
      } 
     } 

    Interlocked.Decrement(ref _threadcounter); 
} 

だから、基本的には明らかなレース(必要な場合)のみ、これまで1つのスレッドを生成するための方法として

+0

忘れないでください:KISS。スレッドセーフキューと1つ(または最大接続数と使用可能なコアに応じてn)の専用送信スレッドを使用してください。ロックレスキューは、ワイヤレイテンシと比較してレイテンシをほとんど追加しません。 –

+0

実際に私の設計上の瑕疵が気付いた。 Factor.Newコールの後にロックを解放しなければならないので、2つのスレッドは新しいスレッドを開始できます。私はconsumerthreadにロックを転送できません。 –

+0

私はクラスを書き直す必要があります。キュー(各接続ごとに1つ)ええ?そうでなければ、何百ものブロックされたキューになる可能性があります(スレッドプールがそれをどのように処理するかわからない) –

答えて

0

を連動カウンタを使用していないが、TryEnterは、いくつかの深刻なアイドル時間の原因です。私は実際に消費者スレッドを常に使用することが最良のソリューションだと考えています。少ししかない場合、オーバーヘッドは本当に小さくなります(正しく設計されていれば、消費者スレッドは動作していないときスリープ状態になります)。

コンシューマスレッドでwhileループを使用しているため、送信されたメッセージごとに新しいタスクを作成し、ロックの競合が大きくなりました。

EDIT:ノンブロッキングソケットを使用しているため、単一のコンシューマスレッドですべての送信要求を処理できるだけである必要があります。単一スレッドのスループットは、ネットワークよりも高くなります。より多くのコンシューマーがいる場合は、ミューテックスを使用してすべてをシリアル化せずに、同じソケットで2つのコンシューマー・スレッドが送信されないようにすることは難しいです。私は、シングルスレッドとマルチスレッドの切り替えは良い考えではないと思います。

現在の「マルチスレッド」ソリューションでは、すべての作業が同じミューテックスを使用して保護されているため、パフォーマンスが向上するわけではありません。これは、単一のスレッドよりも遅く、または遅くなります。

+0

接続ごとに1つの消費者スレッドを提案していますか?または、接続を1つずつ順番に実行するマスタースレッド(クライアント側では違いはありませんが、サーバーに1000秒の接続がある可能性があります) –

+0

データを受信する接続ごとにスレッドが1つありませんか?または、ノンブロッキングソケットを使用していますか? – rasmus

+0

ノンブロッキングrasmus ... –

関連する問題