2

ウィキペディアで言及されている生産者と消費者の問題の「不適切な実装」の擬似コードは次のとおりです。このソリューションには、デッドロックを引き起こす可能性のある競合状態があると言われています。

私の質問は次のとおりです。以下のように他のスレッドをウェイクアップする条件を変更するだけで、デッドロックの問題が解決するわけではありません。そうすれば、失われる可能性のあるウェイクアップが 1 つだけではなく、その後に複数のウェイクアップがあるか、何か不足しています。ここを理解しようとする。

int itemCount = 0;

procedure producer() {
    while (true) {
        item = produceItem();

        if (itemCount == BUFFER_SIZE) {
            sleep();
        }

        putItemIntoBuffer(item);
        itemCount = itemCount + 1;

        //if (itemCount == 1) <<<<<<<< change this to below condition
        if(itemCount > 0)
        {
            wakeup(consumer);
        }
    }
}

procedure consumer() {
    while (true) {

        if (itemCount == 0) {
            sleep();
        }

        item = removeItemFromBuffer();
        itemCount = itemCount - 1;

        //if (itemCount == BUFFER_SIZE - 1) <<<<<<< Change this to below
        if(itermCount < BUFFER_SIZE)
        {
            wakeup(producer);
        }

        consumeItem(item);
    }
}
4

1 に答える 1

1

以下のように他のスレッドをウェイクアップする条件を変更するだけでは、デッドロックの問題が解決されません。

いいえ、競合状態はまだ存在します。問題は、消費および/または生成を行う複数のスレッドがあることです。コンシューマ (たとえば) が起動され、処理するアイテムがあることが通知されると、そのアイテムを削除する可能性がありますが、その前に他のスレッド (または複数のスレッド) がそこに到達しています。

解決策は、次の手順を実行することです。

lock() {
   while (itemCount == 0) {
       sleep();
   }

   item = removeItemFromBuffer();
   itemCount = itemCount - 1;
}

そのため、消費者が目覚めた場合でも、ループで が 0 でないことをすぐに再度確認します。 がインクリメントされたとしても、別のスレッドがその要素を削除し、シグナルを受け取ったスレッドが動作する前にデクリメントした可能性があります。それがレースです。itemCountwhileitemCountitemCount

プロデューサ側でも同じですが、競合はプロデューサがバッファをいっぱいにしないようにすることです。使用可能なスペースがあるためにプロデューサーが起動する場合がありますが、アイテムをバッファーに入れるまでに、他のスレッドがそれを打ち負かし、バッファーを再充填しています。目覚めた後にスペースがあることを確認するために、再度テストする必要があります。

Producer Consumer Thread Race Conditionsというタイトルの私の Web サイトのこのページで、このレースに関する詳細を 1 行ずつ説明します。問題を示す小さなテスト プログラムもあります。

認識すべき重要な点は、ほとんどのロックの実装では、ロックへのアクセスを取得するために待機しているスレッドのキューがあるということです。シグナルがスレッドに送信されると、続行する前に、まずロックを再取得する必要があります。スレッドにシグナルが送信されると、スレッドはBLOCK キューの最後に移動します。ロックを待機しているが待機していない追加のスレッドがある場合、これらのスレッドは起動されたスレッドよりも先に実行され、アイテムを盗みます。

whileこれは、同様のコードのループに関するこの質問と非常によく似ています。残念ながら、受け入れられた回答はこの競合状態に対処していません。ここで同様の質問に対する私の回答に賛成票を投じることを検討してください。偽のウェイクアップ問題ですが、ここでの本当の問題は、ウィキペディアが話している競合状態です。

于 2013-10-09T21:28:55.623 に答える