Защо всички мои нишки спящи с помощта на sleep()?

Видях следната част от кода относно нишките в Linux в мрежата. Но когато го стартирам, всички нишки изглежда спят вместо само основната нишка. Защо? Също така, без sleep(5), изразът-"Нишката е създадена успешно" се изпълнява 3 пъти вместо 2? Може ли някой да обясни това поведение? Благодаря Компилирано с помощта на: gcc -pthread check.c

и моя o/p: Първа обработка на нишкаn Нишка, създадена успешноn Втора обработка на нишкаn Нишка, създадена успешноn

Първите два реда се отпечатват със закъснение от 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
Може да искате да прочетете за откъснато спрямо съединено състояние на нишка, за да разберете защо вашите нишки не изглеждат така, сякаш са приключили. За справка: 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 OS, не мога да премина към linux за момента. Можете ли да ми кажете какво получавате?   -  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

Така че кодът, даден във въпроса, не се държи на моя компютър, както е обяснено във въпроса. Следователно Harsh S. Kulshrestha трябва да редактира въпроса си, като даде точния изходен код , пълната команда за компилиране и точния изход. 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