Почему этот цикл занят не тратит время? - PullRequest
0 голосов
/ 09 апреля 2019

Я только начал изучать многопоточность с книгой "Многопоточность приложений в Win32 - Джим БЕВЕРИДЖ, Роберт ВИЕНЕР". Эта книга с 1997 года.

Начиная со страницы 50 есть раздел на Ожидание занято , и одна из целей состоит в том, чтобы показать, что создание второго потока и ожидание в главном потоке для завершения второго тратит много времени. Существует пример программы на C, которая демонстрирует это, во-первых, синхронизируя функцию, вызываемую в основном потоке, а во-вторых, создавая поток и выполняя работу там, пока основной поток ожидает. Вот программа.

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <time.h>

DWORD WINAPI SomeWork(LPVOID);

int main(int argc, char *argv[])
{
  HANDLE hThrd;
  DWORD exitCode = 0;
  DWORD threadId;
  DWORD begin;
  DWORD elapsed;

  // PART 1: doing the work in the main thread
  puts("Timing normal function call...");
  begin = GetTickCount();
  SomeWork(0);
  elapsed = GetTickCount() - begin;
  printf("Function call took: %d.%.03d seconds\n\n", elapsed / 1000, elapsed % 1000);
  // Result:
  // ===> 1.391 seconds <===


  // PART 2: doing the work in a second thread
  puts("Timing thread + busy loop...");
  begin = GetTickCount();

  hThrd = CreateThread(NULL,
               0,
               SomeWork,
               (LPVOID)1,
               0,
               &threadId);

  // This busy loop (should) chews up a lot of CPU time
  while( 1 ) {
    GetExitCodeThread(hThrd, &exitCode);
    if( exitCode != STILL_ACTIVE ) {
      break;
    }
  }

  elapsed = GetTickCount() - begin;
  printf("Thread + busy loop took: %d.%.03d seconds\n\n", elapsed / 1000, elapsed % 1000);
  // Result:
  // ===> 1.375 seconds <==

  CloseHandle(hThrd);

  printf("Press a key to quit...");
  getchar();
  return EXIT_SUCCESS;
}

// Routine that uses probability to approximate PI.
DWORD WINAPI SomeWork(LPVOID n)
{
  int i;
  int inside = 0;
  double val;

  srand( (unsigned) time(NULL) );

  int TIMES = 10000000;
  for(i=0; i < TIMES; ++i) {
    double x = (double) (rand())/RAND_MAX;
    double y = (double) (rand())/RAND_MAX;
    if( (x*x+y*y) <= 1.0 ) {
      ++inside;
    }
  }
  val = (double)inside / TIMES;
  printf("PI = %.4g\n", val*4);
  return 0;
}

В книге авторы написали полученное время:

Функция, вызываемая в главном потоке: 7,993 секунды.

Функция, вызываемая в другом потоке + занятый цикл: 15,946 секунд.

Однако вот мои меры:

Функция, вызываемая в главном потоке: 1,391 секунды.

Функция, вызываемая в другом потоке + занятый цикл: 1,375 секунды.

Я запускал его несколько раз, и оба раза примерно одинаковы. Итак, мой вопрос, почему они одинаковы? Разве занятая петля не должна съесть много времени? Так как моя машина имеет четыре ядра, может быть, Windows разместил два потока на разных ядрах?

...