Странное поведение этого простого кода - PullRequest
4 голосов
/ 16 августа 2011

Если я скомпилирую и выполню код ниже

  1 #include <iostream>
  2 #include <pthread.h>
  3 #include <cstdio>
  4 #include <cstdlib>
  5
  6 #define NTHREADS 4
  7 #define N 100
  8 #define MEGEXTRA 1000000
  9
 10 using namespace std;
 11
 12 pthread_attr_t attr;
 13
 14 void *doWork (void *threadid) {
 15     double A[N][N];
 16     int tid = *(reinterpret_cast<int *>(threadid));
 17     size_t myStackSize;
 18     pthread_attr_getstacksize (&attr, &myStackSize);
 19     cout << "Thread " << tid << ": stack size = " << myStackSize << " bytes" << endl;
 20
 21     for (int i = 0; i < N; i++) {
 22         for (int j = 0; j < N; j++) {
 23             A[i][j] = ((i * j) / 3.452) + (N - 1);
 24         }
 25     }
 26
 27     pthread_exit (NULL);
 28 }
 29
 30 int main () {
 31     pthread_t threads[NTHREADS];
 32     size_t stackSize;
 33
 34     pthread_attr_init (&attr);
 35     pthread_attr_getstacksize (&attr, &stackSize);
 36
 37     cout << "Default stack size = " << static_cast<long>(stackSize) << endl;
 38
 39     stackSize = sizeof(double) * N * N + MEGEXTRA;
 40     cout << "Amount of stack needed per thread = " << static_cast<long>(stackSize) << endl;
 41
 42     pthread_attr_setstacksize (&attr, stackSize);
 43     cout << "Creating threads with stack size = " << static_cast<long>(stackSize) << endl;
 44
 45     int i[NTHREADS];
 46     for (int j = 0; j < NTHREADS; j++) {
 47         sleep(1);
 48         i[j] = j;
 49
 50         int rc = pthread_create(&threads[j], &attr, doWork, reinterpret_cast<void *>(&i[j]));
 51         if (rc) {
 52            cout << "Error Code: " << rc << endl;
 53             exit (-1);
 54         }
 55     }
 56
 57     cout << "Created " << NTHREADS << " threads" << endl;
 58     pthread_exit(NULL);
 59 }

, я получу следующий вывод:

Default stack size = 8388608
Amount of stack needed per thread = 1080000
Creating threads with stack size = 1080000
Thread 0: stack size = 1080000 bytes
Thread 1: stack size = 1080000 bytes
Thread 2: stack size = 1080000 bytes
Created 4 threads
Thread 3: stack size = 1080000 bytes

, но если я закомментирую sleep (1);в строке 47 я получаю следующий вывод

Default stack size = 8388608
Amount of stack needed per thread = 1080000
Creating threads with stack size = 1080000
Created 4 threads
Thread 3: stack size = 1080000 bytes
Thread 2: stack size = 1080000 bytes
Thread 1: stack size = 1080000 bytes
Thread 9251904: stack size = 1080000 bytes /** ERROR should be Thread 0: stack size = 1080000 /**

Может кто-нибудь объяснить, что происходит?Почему я получаю неправильный вывод с закомментированным sleep (1)?

это то, что я использую для компиляции кода

g++ -Wall -Wextra -O2 -ggdb -pthread 5.cpp -o 5

Ответы [ 3 ]

5 голосов
/ 16 августа 2011

Это связано с тем, что основной поток, который создает другие, завершается (с точностью до pthread_exit - и вы все равно получаете в конце main), прежде чем все созданные потоки успеют запустить , Массив i уничтожается и содержит мусор во время его чтения всеми потоками.

Вы должны подождать, т. Е. pthread_join - ваших дочерних потоков, прежде чем main сможет выйти.

sleep дает вам некоторое время для выполнения потоков, но все еще зависит от ОС, которая решает, кто и когда будет работать. Может случиться, что sleep(1) достаточно или недостаточно, или что никто не бежит, пока почтальон не пришел и не доставил.

Позвоните pthread_join, и вы будете в безопасности.

1 голос
/ 16 августа 2011

Вы не упоминаете, используете ли вы одноядерный компьютер.

Почему вы считаете, что это неверный вывод?

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

0 голосов
/ 16 августа 2011

Когда вы комментируете sleep(1);, основной поток создаст все потоки за один раз и, вероятно, будет быстрее, чем система, порождающая эти потоки. Сами потоки идут параллельно, поэтому их вывод может быть в произвольном порядке Когда вы используете sleep(1); потоки будут созданы, основной поток будет ждать секунду, в то время как этот поток будет запланирован, запущен и выведен гораздо менее чем за секунду, а затем будет создан следующий поток.

created 4 threads будет записано, как только цикл завершится. Без sleep(1); этот цикл завершается непосредственно перед тем, как может запускаться любой из порожденных потоков, поэтому он поступает раньше, чем выводятся потоки. В спящем режиме все потоки, кроме последнего, выходят из своего выхода, когда цикл остается, поэтому Created 4 threads предшествует последнему созданному потоку, который еще не был запланирован.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...