1

C++ キュー (responseQueue) にアクセスし、何らかの処理を行った後に応答を送信する次のコードがあります。

void sendRelpyToClient(){    
    if (responseQueue.empty())
       return;

    static int count = 0;
    Result result;

    SYNCHRONIZE() { //start of synchronization (pseudo-code)

       result = responseQueue.front();
       responseQueue.pop();

    } //end of synchronization

    if(count++ % 9 == 0)
    {
        //simulate some processing with a sleep
        sleep for 15 seconds

    }

    result.sendResult();
}

responseQueueインスタンスが含まれていますResult。メソッドのsendResult()処理に時間がかかる場合があるため、キューに格納されている一部の結果については、メソッドが返されるまでに比較的長い時間がかかる場合があります。メソッドsendRelpyToClient()は複数のスレッドによってアクセスさresult.sendResult()れ、ブロック内にもある場合は、メソッドが戻るのに時間がかかるSYNCHRONIZED()ため、他のスレッドがブロックされる可能性があります。sendResult()これが、私がこのアプローチを選択した理由です。

この実装の私のロジックは、responseQueue にアクセスするすべてのスレッドが最初にキューが空であることを確認して戻るというものです。SYNCHRONIZE()アイテムが 1 つしかない場合、ブロックにアクセスするスレッドはキューを空にするため、SYNCHRONIZE()ブロック内にこのチェックを入れる必要はありません。SYNCHRONIZE()キューにアクセスしている 1 つのスレッドがブロックの直後に (スレッド スケジューラによって) 削除された場合、2 番目のスレッドは再びキュー内の次のアイテムを取得して を呼び出しresult.sendResult()、最初のスレッドが再び再開すると、次のように呼び出しresult.sendResult()を続けます。 result のスレッドローカル値 (スレッドがブロックされる前にキューから取得した値)。上で説明したように、静的カウント変数は、スリープを使用してランダムスレッドの長い処理をシミュレートできるようにするためにあります。sendResult()一部の通話には時間がかかる場合があります。

このコードで一連のテストを実行しましたが、これまでのところ問題なく動作しています。しかし、このアプローチに問題がある場合は、これについてすべてのアイデアを得ることができるように、ここで質問したかっただけです。私は並行プログラミングの専門家ではありません。また、キュー レベルではなく、個々のデータ項目のレベルで並行処理を行う、より効率的でクリーンな方法があれば、それも教えてください。

4

1 に答える 1

2

一般的にあなたのアプローチは正しいですが、私は2つのことに注意したいです:

  1. Xeo によって既に提案されているように、同期ブロック内でキューが空かどうかを確認する必要があります。

  2. グローバル変数である静的変数countがあり、同期せずに複数のスレッドから読み書きします。これはそれほど危険ではありませんが、アルゴリズムが正しく動作しない可能性があります。インクリメントはアトミック操作ではないことに注意してください。2 つのスレッドがカウントの新しい値を同時に書き込む状況が発生する場合があります。

UPD: 修正は簡単です:

    void sendRelpyToClient(){    
        static int count = 0;
        Result result;

        bool execute = false;

        SYNCHRONIZE() { //start of synchronization (pseudo-code)
            if (responseQueue.empty())
               return;
           result = responseQueue.front();
           responseQueue.pop();

           execute = (count++ % 9 == 0);
        } //end of synchronization

        if (execute)
        {
            //simulate some processing with a sleep
            sleep for 15 seconds
        }
        result.sendResult();
    }
于 2012-09-22T15:07:59.187 に答える