2

制限付きバッファーでプロデューサー/コンシューマースレッドを操作しようとしています。バッファーの長さは5です。1つのミューテックスと2つのセマフォがあり、バッファーのサイズで始まる空と、0で始まる完全です。

最後にsleep()を使用せずにコードを実行すると、バッファーが完全にいっぱいになるまで継続的に生成され、空になるまで消費されるため、出力は次のようになります。

Placed 1 in the buffer at position 0.
Placed 2 in the buffer at position 1.
Placed 3 in the buffer at position 2.
Placed 4 in the buffer at position 3.
Placed 5 in the buffer at position 4.
The buffer now contains 0 at position 0.
The buffer now contains 0 at position 1.
The buffer now contains 0 at position 2.
The buffer now contains 0 at position 3.
The buffer now contains 0 at position 4.

ただし、最後にsleep()を使用して実行すると、次のように出力されます。

Placed 1 in the buffer at position 0.
The buffer now contains 0 at position 0.

するとロックされたように見えますが、睡眠の有無に関係なく、なぜそのように動作するのかよくわかりません。助言がありますか?私のメインメソッドは基本的にいくつかの宣言を行い、次に生成するスレッドと消費するスレッドを1つ作成します。これらのメソッドは、以下のとおりです。

void *producer()
{
        int k = 0; //producer index
        while (1)
        {
                sem_wait(&empty);
                pthread_mutex_lock(&mutex);
                buffer[k] = k+1;
                sem_post(&full);
                pthread_mutex_unlock(&mutex);
                printf("Placed %d in the buffer at position %d.\n", buffer[k], k);
                k = (k + 1) % BUFFER_SIZE;
                sleep(rand() * 10);
        }
}

void *consumer()
{
        int j = 0;   //consumer index
        while(1)
        {
                sem_wait(&full);
                pthread_mutex_lock(&mutex);
                buffer[j] = 0;
                sem_post(&empty);
                pthread_mutex_unlock(&mutex);
                printf("The buffer now contains %d at position %d.\n", buffer[j], j);
                j = (j + 1) % BUFFER_SIZE;
                sleep(rand() * 10);

        }
}
4

4 に答える 4

3

toのパラメーターsleep()は、スリープする秒数です。 0から(通常は32767または2 31rand() -1)までの整数を返し、これに10を掛けると、途方もなく長い時間眠っています。あなたは行き​​詰まっておらず、非常に長い間寝ているだけです。RAND_MAX

于 2010-11-05T19:18:41.420 に答える
2

それがデッドロックの理由かどうかはわかりませんがsem_t、特にIOなどが原因で、割り込みが発生する可能性のある機能には注意する必要があります。

システム関数からの戻りを無視しないでください。ここでは、リターンを確認してから、を確認する必要がありerrnoますEINTR

それでは、強制的に使用するかどうかはわかりませんが、sem_tここではを使用する方が自然だと思いますpthread_cond_t。とにかくミューテックスがあるので、これはより簡単に適合します。機能が中断されることはありませんpthread_cond_tpthread_mutex_t

于 2010-11-05T19:17:56.297 に答える
1

Do you have any idea why when I don't include sleep it always produces and consumes in blocks instead of every other?

これはおそらく、コンテキストスイッチが発生する前に、各スレッドに与えられる約30ミリ秒のタイムスライスが、プロデューサーにすべてを生成させるのに十分すぎるためです。

于 2010-11-05T19:53:58.090 に答える
0

両方のスレッドの優先度は同じだと思いますか?そして、これは複数のコアを備えたマシンですか、それとも1つだけですか?セマフォにシグナリングするだけでは現在のスレッドがプリエンプトされないため、現在のスレッドはスライスが期限切れになるまで続行することが期待されます。

また、ミューテックスに信号を送る前に、ミューテックスのロックを確実に解除します。

于 2010-11-05T19:32:14.927 に答える