Почему все мои потоки спят, используя sleep()?

Я видел в Интернете следующий фрагмент кода, касающийся многопоточности в Linux. Но когда я запускаю его, кажется, что все потоки спят, а не только основной поток. Почему? Кроме того, без сна (5) утверждение «Поток успешно создан» выполняется 3 раза вместо 2? Может кто-нибудь объяснить это поведение? Спасибо. Скомпилировано с использованием: gcc -pthread check.c

и мой o/p: обработка первого потока. Поток создан успешно. Обработка второго потока. Поток создан успешно.

Первые две строки печатаются с задержкой в ​​5 секунд, а следующие 2 — еще через 5 секунд. Почему дочерние потоки спят вместо основного?

#include<stdio.h>
#include<string.h>
#include<pthread.h>
#include<stdlib.h>
#include<unistd.h>
pthread_t tid[2];

void* doSomeThing()

{
    unsigned long i = 0;
    pthread_t id = pthread_self();

    if (pthread_equal(id,tid[0]))
    {
        printf("\n First thread processingn");
    }
    else
    {
        printf("\n Second thread processingn");
    }
    return NULL;
}
int main(void)
{
    int i = 0;
    int err;
    while (i < 2)
    {
        err = pthread_create(&(tid[i]), NULL, &doSomeThing, NULL);
        sleep(5);
        if (err != 0)
            printf("\ncan't create thread [%s]", strerror(err))
            else

                printf("\n Thread created successfullyn");
        i++;
        // sleep(5);
    }
    pthread_join(tid[0],NULL);
    pthread_join(tid[1],NULL);

    return 0;
}

person Harsh S. Kulshrestha    schedule 21.02.2015    source источник
comment
Почему doSomeThing берет void arg?   -  person user2357112 supports Monica    schedule 21.02.2015
comment
Вы можете прочитать о состоянии потока detached и joinable, чтобы понять, почему ваши потоки не выглядят так, как если бы они закончились. Для справки: man7.org/linux/man-pages/man3/   -  person alk    schedule 21.02.2015
comment
Как вы написали, ваш код не компилируется. (должно быть void* arg, но вы написали void arg)   -  person Basile Starynkevitch    schedule 21.02.2015
comment
Кстати, я не наблюдаю поведение, которое вы описываете. Я считаю, что код, который вы компилируете, не тот код, который вы нам показываете.   -  person Basile Starynkevitch    schedule 21.02.2015
comment
Я согласен, я изменил этот аргумент o void*, когда он выдал мне ошибку. Проблема в том, что я в настоящее время использую ОС Windows, я не могу переключиться на Linux на данный момент. Не могли бы вы сказать мне, какой o/p вы получаете?   -  person Harsh S. Kulshrestha    schedule 21.02.2015
comment
Пожалуйста, отредактируйте свой вопрос, указав подлинный исходный код (вам нужно добавить четыре пробела перед каждой строкой!), команду компиляции и фактический вывод. Кроме того, скомпилируйте все предупреждения и информацию об отладке (gcc -Wall -Wextra -g). Улучшайте код, пока не появится предупреждение. Узнайте, как использовать отладчик (gdb). Конечно, вы должны установить Linux на свой ноутбук.   -  person Basile Starynkevitch    schedule 21.02.2015
comment
Что касается отсутствующего вывода, вызов fflush() — это один из способов. Однако гораздо лучше просто добавить новую строку (\n) в конец строки, а не в начало. Причина в том, что по умолчанию для многих реализаций вывод буферизуется строкой, поэтому запись новой строки автоматически очищает выходной буфер.   -  person Ulrich Eckhardt    schedule 21.02.2015
comment
Если бы у вас было более одного пункта, я бы понизил ваш вопрос: я объяснил в своем ответе, что вы должны сбросить буфер, а вы этого не сделали. Так какой смысл задавать вопросы, если вы не слушаете ответов?   -  person Basile Starynkevitch    schedule 21.02.2015


Ответы (1)


Как вы думаете, почему все ваши потоки спят? Прочтите руководство по pthreads и pthreads(7)

Похоже, ваши темы очень быстро закрыты. Вы должны были присоединиться к ним (например, до sleep или где-то внутри main), используя pthread_join(3)

 for (int i=0; i<2; i++) {
    void* retval = NULL;
    pthread_join(tid[i], &retval);
    // in your case, since doSomething gives NULL :
    assert (retval == NULL); 
 }

или вы должны были создать отдельные темы, см. pthread_create(3) & пример в pthread_attr_init(3) & pthread_attr_setdetachstate(3) и т. д....

И вы должны были закодировать (поскольку вы ожидаете, что doSomeThing получит аргумент NULL):

void* doSomeThing(void* arg) {
   assert (arg == NULL);

Кстати, скомпилируйте с помощью gcc -Wall -Wextra -g и научитесь использовать отладчик gdb.

Вероятно, вам следует вызвать fflush(3)< /strong> в соответствующих местах (поскольку stdio(3) часто буферизируется), например позвонить fflush(NULL); в конце doSomeThing

Прочтите о неопределенном поведении и постарайтесь избежать его.

Важно делать fflush(NULL); внутри потоков, от которых вы ожидаете вывода (по крайней мере, перед их завершением). Ваш вопрос связан не с sleep, а с буферизацией. И printf часто буферизуется по очень веским соображениям производительности. И вы также должны иметь привычку заканчивать строку управления форматом printf на \n (поскольку это часто приводит к очистке буфера). Ставить \n только в начале строки формата printf — плохая привычка (она должна стоять в конце).


Кстати, исправив строку void* doSomething(void*arg) (поскольку с void arg, как указано в исходной версии вашего вопроса, код даже не компилируется!) Я наблюдаю следующий вывод при компиляции:

 % gcc -Wall -g x.c -pthread -o xx
   x.c: In function 'doSomeThing':
   x.c:11:19: warning: unused variable 'i' [-Wunused-variable]
        unsigned long i = 0;
                      ^

затем выполнение с помощью:

   % ./xx

   Thread created successfully

   First thread processing

   Thread created successfully

   Second thread processing

Таким образом, код, указанный в вопросе, не ведет себя на моем компьютере так, как объясняется в вопросе. Поэтому суровому С. Кулшреста следует отредактировать свой вопрос, указав точный исходный код. , полную команду компиляции и точный вывод. FWIW, моя система — Linux/Debian/Sid на x86-64, gcc — версия 4.9.2, libc — Debian GLIBC 2.19-15

person Basile Starynkevitch    schedule 21.02.2015
comment
Я думаю, что первый параметр pthread_join имеет тип pthreat_t, а не pthread_t *. - person nullptr; 21.02.2015
comment
@BasileStarynkevitch Спасибо за ответ, но я думаю, что поток tid[1] продолжает спать, потому что обработка оператора второго потока печатается только через 5 секунд. - person Harsh S. Kulshrestha; 21.02.2015
comment
Вы добавили звонки на fflush? Без этого данные могут быть все еще буферизованы и не отображаться, когда вы хотите... - person Basile Starynkevitch; 21.02.2015
comment
Да. Кроме того, когда я перемещаю sleep(5) внутри цикла сразу после оператора, в котором вызываются потоки, то есть после этого: err = pthread_create(&(tid[i]), NULL, &doSomeThing, NULL); Оба потока приостанавливаются вместе с основным потоком. Отстраняются ли дети, если отстранен родитель? - person Harsh S. Kulshrestha; 21.02.2015
comment
@BasileStarynkevitch, спасибо за постоянную помощь, чувак. Я разместил свой скомпилированный код здесь: stackoverflow.com/questions/28646159/ Надеюсь, теперь вы понимаете мою проблему. - person Harsh S. Kulshrestha; 21.02.2015
comment
Вы не должны были публиковать новый вопрос. Вы должны были отредактировать это. И вы должны позвонить fflush - person Basile Starynkevitch; 21.02.2015
comment
Ваша проблема состоит в том, чтобы понять, что означает буферизация (это никак не связано с sleep внутри потоков!). Как я уже говорил, вам следует добавить fflush(NULL); в некоторых местах вашего кода. - person Basile Starynkevitch; 21.02.2015