0

redKyle によるチュートリアルのスレッドの使用方法を表示するコードをオンラインで見つけました。「Race Condition」チュートリアルでは、基本的に、2 つのスレッドが関数に送信される方法を示しています。この関数の目的は、「.」を出力することです。および '#' をそれぞれ 100 回ずつ順番に使用します。彼はこれを機能させるためのコードを提供していますが、ミューテックスのコードは提供していません。別のスレッドがアクセスしている間に、あるスレッドが出力された最後の文字を保持する変数にアクセスするのを防ぐために、ミューテックスを含めるようにコードを変更しました。コードが機能するようになりました。すごい!ただし、sleep 値を 1 から 50 の間で変更し続けました。mutex コードは正常に動作します。でも、

コードは次のとおりです。

#include "stdafx.h"

#include <iostream>
#include <windows.h>
using namespace std;

static char lastChar='#';

//define a mutex
HANDLE mutexHandle = NULL;

//flag to specify if thread has begun
bool threadStarted = false;

void threadProc(int *sleepVal, int *threadID)
{

    cout<<"sleepVal: "<<*sleepVal<<endl;

    for (int i=0; i<100; i++)
    {

        char currentChar;

        threadStarted = true;

        while(!threadStarted){}

        //lock mutex
        WaitForSingleObject(mutexHandle, INFINITE);

        if (lastChar == '#')
            currentChar = '.';
        else
            currentChar = '#';

        Sleep(*sleepVal);

        lastChar = currentChar;

        ReleaseMutex(mutexHandle);

        threadStarted = false;


        //      cout<<"\nSleepVal: "<<*sleepVal<<" at: "<<currentChar;
        cout<<currentChar;
    }//end for
}//end threadProc

int main()
{
    cout<<"Race conditions by redKlyde \n";

    int sleepVal1 = 50;
    int sleepVal2 = 30;

    //create mutex
    mutexHandle = CreateMutex(NULL, false, NULL);

    //create thread1
    HANDLE threadHandle;
    threadHandle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) threadProc, &sleepVal1, 0, NULL);

    //create thread2
    HANDLE threadHandle2;
    threadHandle2 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) threadProc, &sleepVal2, 0, NULL);

    WaitForSingleObject(threadHandle, INFINITE);
    WaitForSingleObject(threadHandle2, INFINITE);

    cout<<endl<<endl;

    CloseHandle(mutexHandle);

    system("pause");

    return 0;

}

私の質問は、スリープを 0 に設定するとミューテックス コードが無効になるのはなぜですか。

4

2 に答える 2

1

また、将来相互排除を使用するためのヒントとして、Windows では、SRWLock の後に CriticalSection を使用するのが最適なユーザーモード ミューテックスです。ハンドルベースの同期オブジェクトを使用すると、はるかに遅くなります。

于 2012-05-06T17:21:41.890 に答える
1

print ステートメントはミューテックスによって保護されていないことに注意してください。そのため、1 つのスレッドは自由に印刷でき、もう 1 つのスレッドは自由に変更できます。スリープしないことで、スケジューラがスレッドの量に基づいて印刷順序を決定できるようになります。

いくつか間違っていることがあります:

1) 鍵をかけたまま寝てはいけません。これが正しいことはほとんどありません。2) データが共有される場所はすべて、ロックで保護する必要があります。これは、print ステートメントもロックする必要があることを意味します。

于 2012-04-13T18:56:14.453 に答える