Управление глобальной переменной в потоках

В1) У меня есть приложение, которое работает так, как показано ниже. Мне нужен был механизм ожидания ответа на основе глобальной переменной count. До тех пор каждый вызванный поток приостанавливается.

Ответ Мы можем использовать структуру для отправки аргументов функции 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() безопасно присоединит этот "рабочий" поток, вызванный к так называемому "главному" потоку, из которого этот поток вызывается.

Пожалуйста, дайте мне знать, если для вашего ответа потребуются какие-либо дополнительные данные. Спасибо. Проверьте ответ. собраны из предоставленных ответов.


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
Да Дак. Мне эта процедура помогла. Мне нужно было, чтобы потоки поддерживали свои собственные локальные копии, и создание структуры с переменной count со всеми параметрами, требуемыми моим потоком, решает эту проблему. - 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, но он хочет вырваться из трясины ожидания всех трех одновременно. 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