Блокировка глобального массива в желаемой функции повторного входа в многопоточной программе? - PullRequest
1 голос
/ 30 сентября 2011

Извините, если название вопроса сбивает с толку. Я просто хотел собрать все вещи вместе. У меня есть кусок кода, как:

int newThread(int(*pfunc)())
{
   pthread_t tid;
   pthread_create(&tid, NULL, pfunc, NULL);
   int i = 0;
   while(threads[i] != 0 && i < MAX_NUM_THREADS)
   {
      if ((MAX_NUM_THREADS - 1) == i)
      {
        puts("We've run out of threads' number limit\n");
        return 1;
      }
      ++i;
   } 
   threads[i] = tid;
   pthread_join(tid, NULL);
   return 0;
}

threads [] - глобальный массив. Я хочу сделать эту функцию реентерабельной, но это означает, что я не должен использовать глобальные переменные, насколько я понимаю. Я думаю, это потому, что значения глобальных переменных могут быть непредсказуемыми в определенное время. Но в моем случае массив выглядит вполне предсказуемым.

  1. Это нормально, если я заблокирую массив мьютексом, чтобы сделать эту функцию повторной?
  2. Если да, то как мне сделать это правильно? Просто заблокируйте первый элемент перед использованием и разблокируйте после? или лучше блокировать / разблокировать каждый элемент при доступе к нему?
  3. Возможно ли вообще сделать эту функцию реентерабельной?

1 Ответ

2 голосов
/ 30 сентября 2011

Чтобы сказать, что функция reentrant , она должна полагаться только на то, что локальные переменные будут одновременно вызываться двумя (или более потоками) и возвращать правильные результаты.* Если функция полагается на некоторые общие данные (мы не можем сделать так, чтобы они были повторно введены), мы можем сделать так, чтобы потоко-безопасный вызывался одновременно двумя (или более) потоками, если вседоступ к общим данным сериализуется.

Чтобы сделать вашу функцию поточно-ориентированной, вы должны заблокировать цикл и вставку в threads[].Если вы заблокируете только часть цикла, кто-то может изменить содержимое threads между концом цикла и влиянием на ранг i.

pthread_mutex_t mymutex = PTHREAD_MUTEX_INITIALIZER;

int newThread(int(*pfunc)())
{
   pthread_t tid;
   pthread_create(&tid, NULL, pfunc, NULL);
   int i = 0;
   pthread_mutex_lock(&mymutex);          // take the lock
   while(threads[i] != 0 && i < MAX_NUM_THREADS)
   {
      if ((MAX_NUM_THREADS - 1) == i)
      {
        puts("We've run out of threads' number limit\n");
        pthread_mutex_unlock(&mymutex);   // don't forget to release the lock here too :)
        return 1;
      }
      ++i;
   } 
   threads[i] = tid;
   pthread_mutex_unlock(&mymutex);        // release the lock
   pthread_join(tid, NULL);
   return 0;
}
...