Win32API 複数スレッド間で同期的に整数をインクリメント、デクリメントする InterlockedIncrement, InterlockedDecrement

複数スレッド間で1つの共有オブジェクトにアクセスする際には、同期処理を行う必要がある。複数スレッド間で共有する整数値を同期的にインクリメント、デクリメントを行うには、InterlockedIncrement関数、InterlockedDecrement関数を用いる。


InterlockedIncrementのプロトタイプ

LONG InterlockedIncrement(
  LPLONG lpAddend   // インクリメントするべき変数
);


InterlockedDecrementのプロトタイプ

LONG InterlockedDecrement(
  LPLONG lpAddend   // デクリメントするべき変数
);


  • 使用例

  • 複数のインクリメント用スレッドとデクリメント用スレッドが1つの整数型グローバル変数 g_dwCount にアクセスし、インクリメントとデクリメントを同じ回数だけ行う。スレッドの同期処理を行っているため、最終的には整数型グローバル変数 g_dwCount は初期値であるゼロに戻っている。

    #include <windows.h>
    #include <process.h>
    #include <stdio.h>
    
    DWORD g_dwCount = 0;
    
    unsigned int WINAPI IncrementThread(void *arg)
    {
      for (int i = 0; i < 100; i++) {
        InterlockedIncrement((volatile LONG*)&g_dwCount);
        printf("Increment: g_dwCount = %u\n", g_dwCount);
        Sleep(rand() % 10);
      }
      return 0;
    }
    
    unsigned int WINAPI DecrementThread(void *arg)
    {
      for (int i = 0; i < 100; i++) {
        InterlockedDecrement((volatile LONG*)&g_dwCount);
        printf("Decrement: g_dwCount = %u\n", g_dwCount);
        Sleep(rand() % 20);
      }
      return 0;
    }
    
    int main()
    {
      HANDLE hThreads[100];
      size_t nThreads = sizeof(hThreads) / sizeof(hThreads[0]);
      unsigned int uiThreadId;
    
      for (size_t i = 0; i < nThreads; i++) {
        hThreads[i] = (HANDLE)_beginthreadex(NULL, 
          0, 
          i % 2 == 0 ? IncrementThread : DecrementThread, 
          NULL, 
          0, 
          &uiThreadId);
      }
    
      for (size_t i = 0; i < nThreads; i++) {
        WaitForSingleObject(hThreads[i], INFINITE);
      }
    
      for (size_t i = 0; i < nThreads; i++) {
        CloseHandle(hThreads[i]);
      }
    
      printf("Result of g_dwCount = %u\n", g_dwCount);
    
      return 0;
    }


    参考
    http://msdn.microsoft.com/ja-jp/library/cc429236.aspx
    http://msdn.microsoft.com/ja-jp/library/cc429229.aspx