13

pthreads を使用してマルチスレッド C アプリケーションに取り組んでいます。データベースに書き込む 1 つのスレッド (データベース ライブラリは単一のスレッドでのみ安全に使用できます) と、データを収集して処理し、結果をデータベース スレッドに送信して保存する必要があるいくつかのスレッドがあります。C で複数ライターのセーフ キューを作成することは「可能」であると言及されているのを見てきましたが、これについて言及されているすべての場所で、「この例では複雑すぎる」と単純に述べられており、単一ライターのセーフ キューを示しているだけです。 .

次のものが必要です。

  • 効率的な挿入と取り外し。他のキューと同様に、O(1) のエンキューとデキューが可能であると想定します。
  • 動的に割り当てられたメモリ、つまりリンクされた構造。キューのサイズに恣意的な制限を設ける必要はないので、配列は実際には探しているものではありません。

編集:読み取りスレッドは、空のキューでスピンしないでください。書き込みがなく、多数の書き込みの短いバーストが数分ある可能性があるためです。

4

4 に答える 4

19

確かに、ロックレス キューがあります。ただし、コメントで述べたことに基づいて、書き込みごとにスレッドを作成しているため、ここでのパフォーマンスはまったく重要ではありません。

したがって、これは条件変数の標準的な使用例です。ミューテックス、条件変数、リンク リスト (または必要に応じて循環バッファー)、およびキャンセル フラグを含む構造体を作成します。

write:
    lock the mutex
    (optionally - check the cancel flag to prevent leaks of stuff on the list)
    add the event to the list
    signal the condition variable
    unlock the mutex

read:
   lock the mutex
   while (list is empty AND cancel is false):
       wait on the condition variable with the mutex
   if cancel is false:  // or "if list non-empty", depending on cancel semantics
       remove an event from the list
   unlock the mutex
   return event if we have one, else NULL meaning "cancelled"

cancel:
   lock the mutex
   set the cancel flag
   (optionally - dispose of anything on the list, since the reader will quit)
   signal the condition variable
   unlock the mutex

外部ノードでリストを使用している場合は、メモリを保持する時間を短縮するために、ミューテックス ロックの外側にメモリを割り当てたい場合があります。しかし、侵入型のリスト ノードを使用してイベントを設計する場合は、おそらく最も簡単です。

編集:キャンセル時に「シグナル」を「ブロードキャスト」に変更すると、複数のリーダーをサポートすることもできます(特定のイベントを取得するポータブル保証はありません)。必要ありませんが、費用もかかりません。

于 2009-07-31T14:32:04.777 に答える
5

ロックのないキューが必要ない場合は、既存のキューをロックでラップすることができます。

Mutex myQueueLock;
Queue myQueue; 
void mtQueuePush(int value)
{
    lock(myQueueLock);
    queuePush(myQueue, value);
    unlock(myQueueLock);
}
int mtQueueNext()
{
    lock(myQueueLock);
    int value = queueFront(myQueue);
    queuePop(myQueue);
    unlock(myQueueLock);
    return value;
}

その後の唯一のことは、キューが空のときに mtQueueNext に何らかの処理を追加することです。

編集: リーダーが 1 つ、ライターが 1 つのロックレス キューの場合、mtQueuePush の周りにロックを設定するだけで、複数の同時ライターを防ぐことができます。

単一のリーダー/ライター ロックレス キューは数多くありますが、そのほとんどは C++ テンプレート クラスとして実装されています。ただし、Google検索を行い、必要に応じてプレーンCで書き直す方法を見つけてください.

于 2009-07-31T14:18:48.963 に答える
4

http://www.liblfds.org

C で書かれたロックフリーのデータ構造ライブラリ。

M&S キューがあります。

于 2012-05-23T18:44:44.783 に答える
1

複数の単一ライター キュー (ライター スレッドごとに 1 つ) を使用します。次に、単一のリーダーにさまざまなキューを読み取らせる方法について、これを確認できます。

于 2009-07-31T13:53:01.813 に答える