0

PrintHello()関数 pthreads の例はスレッドセーフですか? この種の例をオンラインで見つけましたが、スレッドセーフにする方法がわかりません。一方、関数内のコードの周りにミューテックスを追加するPrintHello()と、前のスレッドが関数を終了するのを待ってすべてのスレッドがキューに入れられるため、例はマルチスレッド化されませんPrintHello()。また、非静的関数へのポインターは許可されていないCreateThread()ように見えるため、メンバーを静的に宣言する必要があるため、クラスに移動しても役に立ちません。これを解決する方法はありますか?

#include <WinBase.h>
#include <stdio.h>
#include <stdlib.h>     /* srand, rand */
#include <time.h>       /* time */

#define NUM_THREADS     500

DWORD PrintHello(LPVOID oHdlRequest)
{
   long tid;
   tid = (long)GetCurrentThreadId();

   /* randomly sleep between 1 and 10 seconds */
   int sleepTime = rand() % 10 + 1;   
   sleep(sleepTime);

   printf("Hello World! It's me, thread #%ld!\n", tid);
   return 0;
}

int main (int argc, char *argv[])
{
   /* initialize random seed: */
   srand (time(NULL));

   HANDLE threads[NUM_THREADS];
   long t;
   DWORD nThreadID;

   for(t=0; t<NUM_THREADS; t++){
      printf("In main: creating thread %ld\n", t);

      threads[t] = CreateThread(
            // Default security
            NULL, 
            // Default stack size
            0, 
            // Function to execute
            (LPTHREAD_START_ROUTINE)&PrintHello,
            // Thread argument
            NULL,
            // Start the new thread immediately
            0, 
            // Thread Id
            &nThreadID
        );    

      if (!threads[t]){
         printf("ERROR; return code from CreateThread() is %d\n", GetLastError());
         exit(-1);
      }
   }
}
4

2 に答える 2

6

を含めているのでWinBase.h、MSVC を使用していると仮定します。MSVC CRT は長い間マルチスレッド アクセスをサポートしてきました。実際、現在のバージョンの MSVC は、スレッドセーフではないシングル スレッド CRT をサポートしていません。VS 2003 は、シングル スレッド CRT をサポートする MSVC の最後のバージョンであると思います。

マルチスレッド CRT では、関数はスレッド セーフであり、グローバル データに内部的にアクセスする場合、関数間で同期されます。したがって、printf()実行されるそれぞれは、他のスレッドProcessRequest()の他の呼び出しに対してアトミックになりますprintf()(実際には、ロックはストリームに基づいているため、printf()呼び出しは を使用する他の CRT 関数に対してアトミックになりますstdout)。

これに対する例外は、ロックを取得しないように明示的に文書化されている I/O 関数を使用する場合 (パフォーマンス上の理由から自分で同期できるようにするため)、または_CRT_DISABLE_PERFCRIT_LOCKSCRT がすべての I/O がロックされると想定する場合を定義する場合です。単一のスレッドで実行されます。

http://msdn.microsoft.com/en-us/library/ms235505.aspxを参照してください。

printf()POSIX は、スレッドセーフになる同様の保証を行います。

  • http://pubs.opengroup.org/onlinepubs/9699919799/functions/flockfile.html

    (FILE *) オブジェクトを参照するすべての関数は、名前が _unlocked で終わるものを除いて、内部で flockfile() および funlockfile() を使用してこれらの (FILE *) オブジェクトの所有権を取得するかのように動作します。

  • http://newsgroups.derkeiler.com/Archive/Comp/comp.programming.threads/2009-06/msg00058.html (David Butenhof による投稿):

    POSIX/UNIX では、printf() 自体がアトミックである必要があります。別々のスレッドからの printf() への 2 つの並列呼び出しでデータを混合することはできません。ただし、これらの 2 つの書き込みは、どちらの順序でも出力に表示される可能性があります。

于 2013-05-13T08:17:22.703 に答える