Контрол върху глобалната променлива в нишките

Q1) Имам приложение, което изпълнява функции, както е показано по-долу. Имах нужда от механизъм за изчакване на отговора въз основа на променливата за глобален брой. Дотогава всяка извикана нишка е заспала.

Отг. Можем да използваме структура, която да изпратим като аргументи на pthread_create()

typedef args
{
    int arg;
    int gcount;
}sargs;

sargs threadarg[3];

int main()
{
    /** Pass the structure after initializing to pthread_create() and access
    these values when required*/
}

Q2) Мога ли да обвържа всяка нишка с една и съща функция без условия за състезание.?

Отг. да

Псевдо код:

int gcount[3];
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;

main()
{
    pthread_t th[3];
    int arg[3];
    gcount[0]=10;
    gcount[1]=10;
    gcount[2]=10;


    // arg array is filled up with 3 different data values 

    // "same_func()" function is used to invoke the threads with different arg' values
    for( i =0; i< 3; i++)
        pthread_create(&th[i], NULL, same_func, arg[i]);

   for( i = 0;i <3; i++ )
        pthread_join(th[i], NULL)

    return 0;
}

void same_func( void *val)
{
   //Perform sending of this val using send() function for 10 times in each thread.
   // Basically I will be sending some specific data along with "val"

  //This part is troubling me.
  // I need to wait on until the global count decreases based on callback function as shown
  // I am not sure of using "gcount" variable in this way. Wants inputs in here.

   while( gcount[0] > 0 || gcount[1] > 0 || gcount[2] >0 )
       sleep(1);

   pthread_exit(NULL);
}

// This function is invoked when I receive response to the above send()
void callback( void *val)
{
  //Performs some work

  pthread_mutex_lock(&lock);

   if(val == arg[0])
       gcount[0]--;

   if(val == arg[1])
       gcount[1]--;

   if(val == arg[2])
       gcount[2]--;

   pthread_mutex_unlock(&lock);    
}

Q3) Освен това, когато извикам pthread_join().. Ще изчака ли, докато моята нишка продължи да чака. Или ще върне някаква стойност за грешка и ще направи нишката "зомби"??

Отг. Pthread_join() ще се присъедини безопасно към тази "работна" нишка, извикана към така наречената "главна" нишка, откъдето тази нишка се извиква.

Моля, уведомете ме, ако са необходими допълнителни данни, за да отговорите. Благодаря. Проверете Ans. събрани от дадените отговори.


person Adit Ya    schedule 21.11.2013    source източник


Отговори (2)


(1) Променливите на условията са най-добрият залог Вероятно семафори в зависимост от това какво наистина правите.

(2) Да, освен ако няма нещо фундаментално пикантно във вашата send функция, т.е. вие сте зависими от някакъв конкретен ред на изпращания между нишките. В противен случай трябва да защитите споделените ресурси с мутекси.

(3) pthread_join ще продължи да блокира, докато нишката, която чакате, завърши. Обърнете внимание, че няма гаранция, че нишките ще завършат във всякакъв ред, така че ако чакате на th[0] е възможно 1 и 2 да завършат първи и просто ще ги вземете в цикъла, когато стигнете до тях.

person Duck    schedule 21.11.2013
comment
Как мога да използвам променливата gcount, за да изчакам вътре в same_func(). Защото в момента използвам всички глобални променливи, налични за заспиване, но това означава, че всички нишки се затварят от same_func(), след като условието е неуспешно. Но искам нишката да изчака, докато бъде изпълнен глобалният брой, който е уникален за условието на нишката. - person Adit Ya; 21.11.2013
comment
same_func е функцията за стартиране на вашата нишка. Създайте структура, съдържаща всякакви променливи, от които се нуждаете, и предайте указател към тях към same_func като 4-ти параметър към pthread_create. same_func го предава на обратно извикване, точно както правите в момента. - person Duck; 21.11.2013
comment
Да Дък. Намерих тази процедура за полезна. Имах нужда от нишки, за да поддържам свои собствени локални копия и създаването на структура с променливата за броене с всички параметри, изисквани от моята нишка, решава този проблем. - person Adit Ya; 23.11.2013

Бихте използвали условна променлива, за да изчакате променливите gcount да достигнат нула:

int gcount[3];
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthraed_cond_t cond = PTHREAD_COND_INITIALIZER;

void same_func(void *val)
{
   //Perform sending of this val using send() function for 10 times in each thread.
   // Basically I will be sending some specific data along with "val"

   /* Wait for all `gcount[]` values to reach zero */
   pthread_mutex_lock(&lock);
   while (gcount[0] > 0 || gcount[1] > 0 || gcount[2] > 0)
       pthread_cond_wait(&cond, &lock);
   pthread_mutex_unlock(&lock);

   pthread_exit(NULL);
}

Във функцията за обратно извикване трябва да сигнализирате променливата на условието:

void callback(void *val)
{
  //Performs some work

  pthread_mutex_lock(&lock);

   if(val == arg[0])
       gcount[0]--;

   if(val == arg[1])
       gcount[1]--;

   if(val == arg[2])
       gcount[2]--;

   if (gcount[0] <= 0 && gcount[1] <= 0 && gcount[2] <= 0)
       pthread_cond_broadcast(&cond);

   pthread_mutex_unlock(&lock);    
}
person caf    schedule 22.11.2013
comment
Мисля, че това е основно кодът, който OP търси, но той иска да се измъкне от блатото на чакане на всичките 3 едновременно. IOW той иска всяка нишка да изпрати 10 съобщения и след това всяка отделна нишка да блокира на своя брояч, докато не се върнат всички 10 отговора. Така че основно това с един gcount елемент и свързан condvar за нишка. - person Duck; 22.11.2013
comment
Това ще накара всички нишки да излязат много преди да се изпълни цялата функционалност на нишката, когато само една от нишките може да е завършила работата си. - person Adit Ya; 23.11.2013
comment
Не, с този код никоя нишка няма да излезе, докато всички gcount[] променливи не достигнат нула. Това се основава на условието в цикъла while () sleep(); във вашия въпрос. - person caf; 24.11.2013