4

Cでは、値を生成するスレッドがいくつかあり、それら を消費するスレッドが1つあります。したがって、ウィキペディアの実装と同様の方法で実装された固定サイズのバッファーと、スレッドセーフな方法でそれにアクセスするメソッドが必要です。long

一般的なレベルでは、次のことが当てはまります。

  • フルバッファに追加するときは、スレッドをブロックする必要があります(古い値を上書きしないでください)。
  • コンシューマースレッドは、バッファーがいっぱいになるまでブロックする必要があります。そのジョブには一定のコストが高く、可能な限り多くの作業を行う必要があります。(これはダブルバッファーソリューションを必要としますか?)

できればライブラリからの、試行錯誤された実装を使用したいと思います。何か案は?


動機と説明:

ヒープオブジェクトにタグとして保持されているグローバル参照の削除を処理するJNIコードを書いています。

ObjectFreeJVMTIイベントが発生すると、を使用して解放する必要があるグローバル参照を表すタグを取得しlongますDeleteGlobalRef。このために、私はJNIEnv参照が必要です-そしてそれを取得することは本当に費用がかかるので、私はリクエストをバッファリングして一度にできるだけ多くを削除したいと思います。

イベントを受信するスレッドが多数ある可能性がありObjectFree、参照の削除を行うスレッド(私のもの)が1つあります。

4

3 に答える 3

1

あなたは考慮に入れて状態を考慮したいかもしれません。消費者向けのこのコードを見てください:

while( load == 0 )
    pthread_cond_wait( &notEmpty, &mutex );

負荷(リスト内の要素の数を格納する場所)がゼロかどうかを確認し、ゼロの場合は、プロデューサーが新しいアイテムを生成してリストに追加するまで待機します。
プロデューサーにも同じ条件を実装する必要があります(アイテムを完全なリストに入れたい場合)

于 2012-08-28T19:23:26.177 に答える
1

アクセス時にミューテックスを使用して、単一のバッファーを使用できます。使用されている要素の数を追跡する必要があります。「シグナリング」には、条件変数を使用できます。プロデューサースレッドがデータをキューに入れるたびにトリガーされるもの。これにより、コンシューマスレッドが解放され、空になるまでキューが処理されます。もう1つは、キューを空にしたときにコンシューマースレッドによってトリガーされます。これは、ブロックされたプロデューサースレッドにキューを埋めるように通知します。コンシューマーの場合、特にデキュー操作が単純で高速であるため、ロックを解除する前に、キューをロックし、可能な限り取り出すことをお勧めします(ロックが多すぎないようにするため)。


いくつかの有用なリンクを更新
します: *ウィキペディアの説明
* POSIXスレッド
* MSDN

于 2012-08-28T16:06:00.550 に答える
1

2つの可能性:

a)malloc()*いくつかのlongとインデックスを保持する配列を持つ*Buffer構造体-ロックは必要ありません。各プロデューサースレッドに独自の*Bufferを割り当て、ロードを開始します。プロデューサースレッドが最後の配列位置を埋めたら、* Bufferをプロデューサー-コンシューマーキューのコンシューマースレッドにキューイングし、すぐに新しい* Bufferをmalloc()します。コンシューマーは*Buffersを取得して処理し、次にそれらをfree()します(またはそれらを別の場所にキューに入れるか、プロデューサーが再利用するためにプールにプッシュします)。これにより、バッファ自体のロックが回避され、PCキューのロックのみが残ります。問題は、longをたまにしか生成しないプロデューサーは、* Bufferがいっぱいになるまでデータを処理しないことです。これには時間がかかる場合があります(このようなスレッドでは、配列がいっぱいになる前にBufferをプッシュすることができます。

b)いくつかのlongとインデックスを保持する配列を使用してBuffer構造体を宣言します。mutex / futex/CSロックで保護します。malloc()は1つの共有*バッファーであり、すべてのスレッドにロックを取得させ、長いスレッドをプッシュしてロックを解放します。スレッドが最後の配列位置にプッシュした場合は、* Bufferをプロデューサー-コンシューマーキューのコンシューマースレッドにキューイングし、すぐに新しい*Bufferをmallocしてからロックを解除します。コンシューマーは*Buffersを取得して処理し、次にそれらをfree()します(またはそれらを別の場所にキューに入れるか、プロデューサーが再利用するためにプールにプッシュします)。

于 2012-08-28T18:32:29.793 に答える