誰かがこれを正しく設計するのを助けることができます。リソースがビジー状態の場合に限り、スレッドとワーカーキューを生成する
私の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つのスレッドを生成するための方法として
忘れないでください:KISS。スレッドセーフキューと1つ(または最大接続数と使用可能なコアに応じてn)の専用送信スレッドを使用してください。ロックレスキューは、ワイヤレイテンシと比較してレイテンシをほとんど追加しません。 –
実際に私の設計上の瑕疵が気付いた。 Factor.Newコールの後にロックを解放しなければならないので、2つのスレッドは新しいスレッドを開始できます。私はconsumerthreadにロックを転送できません。 –
私はクラスを書き直す必要があります。キュー(各接続ごとに1つ)ええ?そうでなければ、何百ものブロックされたキューになる可能性があります(スレッドプールがそれをどのように処理するかわからない) –