0

マルチスレッドプログラムを作成しました。ここでは、1 つのスレッドが「Hello」を出力し、別のスレッドが「World」を出力し、出力は「Hello World」を 50 回出力します。正常に動作しますが、イベントを使用しています。これはカーネル オブジェクトであり、ユーザー モードとカーネルを切り替える必要があります。C#やJavaではなく、VC ++の軽量バージョンを提案できますか。

  #include <Windows.h>


static HANDLE event1 = CreateEvent(NULL, TRUE, TRUE, NULL); 
static HANDLE event2 = CreateEvent(NULL, TRUE, TRUE, NULL); 


DWORD WINAPI ThreadHello(  __in  LPVOID lpParameter)
{
    for( int i = 0 ; i < 50 ; i++ )
    {
        WaitForSingleObject(event1, INFINITE);
        ResetEvent(event1);
        printf("%s ", "Hello");
        SetEvent(event2);
    }

    return 1;
}

DWORD WINAPI ThreadWorld(  __in  LPVOID lpParameter)
{
    for( int i = 0 ; i < 50 ; i++)
    {
        WaitForSingleObject(event2, INFINITE);
        ResetEvent(event2);
        printf("%s\n", "World");
        SetEvent(event1);
    }

    return 1;
}


int _tmain(int argc, _TCHAR* argv[])
{
    CreateThread(NULL, 0, ThreadHello, (LPVOID)0, 0, 0);
    CreateThread(NULL, 0, ThreadWorld, (LPVOID)0, 0, 0);

    getchar();

    return 0;
}
4

4 に答える 4

2

なぜ複数のスレッドでこれをやろうとしているのですか? 現在、スレッドはロックステップ方式で実行されています。つまり、一度に実行されるスレッドは 1 つだけです。この場合、代わりに単一のスレッドを使用するように再設計します。

同時実行のためではなく、コードを明確にするためにこれを行っている場合 (まれなケースですが、まだ可能です)、fiberの使用を検討してください。コード構造はスレッドの場合とほぼ同じですが、イベントを設定して待機する代わりに、現在のファイバーをプリエンプトして、 SwitchToFiberへの呼び出しを介して他のファイバーを実行します。

マルチスレッドを使用する必要がある主なケースは次のとおりです。

  1. 複数の部分に分割できる CPU バウンドの問題がある場合 - 印刷プロセスは CPU バウンドである可能性がありますが、複数の部分に分割することはできません。ファイル読み取りの問題は、CPU バウンドではない可能性があります。
  2. 非同期呼び出しをサポートしないライブラリを扱い、バックグラウンドで何かを実行する必要がある場合。
  3. コードが単純になり、オーバーヘッドを気にしないためです。たとえば、サーバー アプリケーションでスレッドごとに 1 つの要求を処理する場合などです。
于 2012-09-12T14:37:09.270 に答える
1

私はその質問が一般的であることを理解しています。このようなシナリオは、クリティカルセクションオブジェクトを使用して対処することもできます。

DWORD WINAPI ThreadHello(  __in  LPVOID lpParameter)
{
  for( int i = 0 ; i < 50 ; i++ )
  {
    EnterCriticalSection(&csMyCriticalSectionObject);
    printf("%s ", "Hello");
    LeaveCriticalSection(&csMyCriticalSectionObject);
    // now we're ending the threads quantum
    Sleep(0);
    // ThreadWord is waiting on EnterCriticalSection, thus ready to execute and
    // therefore executed next.
  }
  return 1;
}

DWORD WINAPI ThreadWorld(  __in  LPVOID lpParameter)
{
  for( int i = 0 ; i < 50 ; i++)
  {
    EnterCriticalSection(&csMyCriticalSectionObject);
    printf("%s\n", "World");
    LeaveCriticalSection(&csMyCriticalSectionObject);
    // now we're ending the threads quantum
    Sleep(0);
    // ThreadHello is waiting on EnterCriticalSection, thus ready to execute and
    // therefore executed next.
  }
  return 1;
}


// global
CRITICAL_SECTION csMyCriticalSectionObject;


int _tmain(int argc, _TCHAR* argv[])
{
  // initialize the critical section object
  InitializeCriticalSection(&csMyCriticalSectionObject);

  CreateThread(NULL, 0, ThreadHello, (LPVOID)0, 0, 0);
  CreateThread(NULL, 0, ThreadWorld, (LPVOID)0, 0, 0);

  getchar();

  return 0;
}

マルチスレッドバッファ出力が必要な場合は、キューイングメカニズム、たとえば同期FIFOを検討する必要があります。すべての出力は、任意の数のスレッドによってそのキューにキューイングされる可能性があります。単一の出力スレッドが出力(printf)にデキューできます。

于 2012-09-12T15:42:32.190 に答える
1

ロックを取得する試みを待つのに忙しいアトミックコンペアアンドスワップを試してください。それは忙しいので待つという点で粗雑ですが、それはあなたに有用な技術のいくらかの経験を与えるでしょう。

于 2012-09-12T14:42:28.293 に答える
0

問題のドメインはあまりにも曖昧で抽象的であり、実際には適切なマルチスレッド プログラミングとしての資格がありません。あなたが学習段階にあることは理解していますが、現実的である必要があります。ユーザー入力を取得し、ファイルを読み取り、外部イベント (時刻/時刻、ファイル変更、ユーザー ログイン、ダウンロードの完了など) を待機し、スレッド (リーダー スレッド、ライター スレッド) との間で適切に同期する必要があります。

あなたが抱えている問題については、クリティカル セクションまたはリーダー ライター ロックを試してみるのもよいでしょう。

于 2012-09-12T18:30:46.830 に答える