5

いくつかのスレッド間でC#(.NET)オブジェクトを共有しているという問題に直面しています。スレッドがオブジェクトを別のオブジェクトに置き換える場合があります。スレッドは、非同期フレームワークを使用してTCP/IP接続からウェイクアップされます。

順序:

スレッド(接続を待機中)->非同期コールバック->スレッドセーフな処理を実行->共有オブジェクトへのアクセス->スレッドセーフな処理を実行

1.ソリューションミューテックス:

Object sharedObject = new Object();
Mutex objectMutex = new Mutex();

void threadCallback()
{
  Object newObject = new Object();

  // some processing

  objectMutex.lock();
  // do exchange sharedObject with newObject if needed
  // very little processing here
  objectMutex.unlock();

  // some processing
}

2.ソリューションインターロック

Object sharedObject = new Object();
int usingSharedObject = 0;

void threadCallback()
{
  Object newObject = new Object();

  // some processing

  // poll until we lock
  while(1 == Interlocked.Exchange(ref usingSharedObject , 1))
  {
    // do exchange sharedObject with newObject if needed
    // very little processing here
    Interlocked.Exchange(ref usingSharedObject , 0); // free lock
  }

  // some processing
}

何がより速く、より良くスケールアップしますか?

同時にポーリングするスレッドが多くない限り、2番目のソリューションの方が高速であると思います。2番目のソリューションは、ポーリングが処理時間を浪費しないように、ランダムな時間スリープする場合もあります。私が本当にたくさんのTCP/IP接続を処理する必要がある場合、最初の解決策は私にはきれいに見えます。TCP / IP処理に関して、ロックされたセクションではほとんど処理を行わないので、スケールアップの問題はありますか?

threadCallback()関数の開始時にオブジェクトを作成するのはどうですか。

私のC++のバックグラウンドでは、このような状況では常にメモリプールを使用していました。これは、安全な.NETを使用する必要があるためです。新しいオブジェクトをすばやく作成する方法があるか、この分野で.NETプラットフォームが適切に機能します。

よろしくお願いします、

フリードリヒ

4

5 に答える 5

5

インターロックされた操作が正しくありません。スピンロックは通常、次のようになります。

int sharedLock = 0;

void callback()
{

do {
 int existingState = Interlocked.CompareExchange(ref sharedLock, 1, 0);
 if (0 == existingState) {
  break;
 }
} while (true);

try
{
 // operate on the shared state
}
finally
{
 int existingState = Interlocked.Exchange(ref sharedLock, 0);
 Debug.Assert (1 == existingState);
}

}

どちらを使用するのかという理由は、主にロックをかけたままの操作の種類によって異なります。非常に短い操作(短い算術加算/減算、単純な状態フラグの変更など)は、スピンロックに適しています。重い操作(割り当て、IOアクセス)はスピンロックでは発生しないため、真のミューテックスで実行する必要があります。

于 2010-02-03T16:39:42.037 に答える
3

一見すると、2つの例は同等ではないように見えます。Interlocked.Exchange()他の何かが「自家製セマフォ」を要求している間、使用しているポーリングソリューションは処理ループにドロップし、自家製セマフォが要求された場合はスワッピングをスキップするsharedObjectように見えますnewObject。(私が何かを誤解していない限り、それはかなり可能です)。

正確性の問題はパフォーマンスの問題よりも重要であり、同期プリミティブは正しくするのが非常に難しい場合があるため、Mutex最初に解決策を検討し、問題が判明した場合は別の解決策を探します。

Win32は、スピンカウントを備えたmutexオブジェクトを追加して、ここで実行しようとしていることの両方の世界を最大限に活用できるようにしました(私は思います)。ただし、私が知る限り、.NETFrameworkではまだ公開されていません。

于 2010-02-03T16:31:03.337 に答える
2

2番目の例の動作を見ると、ロックが取得されていない場合は、コードの重要な部分をスキップして終了するようです。

Mutexのアプローチははるかに理解しやすく、パフォーマンスの問題は発生していません。

于 2010-02-03T16:31:20.590 に答える
1

もっとエキゾチックなものを使う必要があると確信できるまで、Mutex()ルートを使います。

また、重量が心配な場合は、モニター(またはc#ロックステートメント-同じこと)の使用を検討してください。ロック/モニターは、Mutexよりも優れたパフォーマンスを発揮します。ただし、プロセスの外部には表示されません(ただし、名前付きのMutexを作成していないため、プロセスの外部に表示する必要はないように見えます)。

于 2010-02-03T17:07:45.013 に答える
0

.Net 4を使用している場合は、新しいSpinLock構造を確認することもできます。

于 2010-02-03T17:11:58.610 に答える