Нитевой барьер на 49 нитей - PullRequest
0 голосов
/ 23 апреля 2020

Я должен создать 49 потоков в определенном процессе (в моей задаче несколько процессов, поэтому давайте назовем процесс P3). Я создал эти потоки, но проблема возникает здесь: в любое время максимум 5 потоков могут работать в P3 без учета основного процесса. Поток 13 из P3 может завершаться только в том случае, если в общей сложности запущено 5 потоков (поток 13 входит в число этих 5 потоков). Мой вопрос: как мне убедиться, что в какой-то момент выполнения программы будет запущено 5 потоков, и среди них будет Поток 13, чтобы он мог завершить свое выполнение. Я использую C в качестве языка программирования и Linux системные вызовы. Более того, мне не разрешено использовать «sleep ()» и «usleep ()».

Это функция, в которой я считаю количество потоков.

`void * thread_function2 ( void * arg) {

TH_STRUCT* st=(TH_STRUCT*)arg;



sem_wait(&sem);

sem_wait(&sem2);
nrThreads++;
sem_post(&sem2);

printf("Number of threads running: %d\n",nrThreads);




sem_wait(&sem3);
nrThreads--;
sem_post(&sem3);

sem_post(&sem);

return 0;

} `

Эта часть из основного потока, в котором я создаю свои темы: sem_init(&sem,0,5); sem_init(&sem2,0,1); sem_init(&sem3,0,1); sem_init(&sem4,0,1);

        for(int i=1;i<=49;i++)
        {
            params1[i].procNum=3;
            params1[i].threadNum=i;
            pthread_create(&tids1[i],NULL,thread_function2,&params1[i]);
        }

`

Начало потока выполняется с помощью функции fuction info (args), которая печатает слово BEGIn и номер потока.
Завершение потока выполняется с помощью функции info (args), которая печатает слово END и поток число.
Это пример вывода и того, что делают потоки, когда они начинаются и когда они заканчиваются:

[ ] BEGIN P5 T0 pid=30059 ppid=30009 tid=-99981504  
[ ]  END  P5 T0 pid=30059 ppid=30009 tid=-99981504  
[ ] BEGIN P6 T0 pid=30060 ppid=30009 tid=-99981504  
[ ]  END  P6 T0 pid=30060 ppid=30009 tid=-99981504  
[ ] BEGIN P7 T0 pid=30061 ppid=30009 tid=-99981504  
[ ]  END  P7 T0 pid=30061 ppid=30009 tid=-99981504  
[ ] BEGIN P8 T0 pid=30062 ppid=30009 tid=-99981504  
[ ]  END  P8 T0 pid=30062 ppid=30009 tid=-99981504  
[ ]  END  P3 T0 pid=30009 ppid=30006 tid=-99981504  
[ ] BEGIN P9 T0 pid=30063 ppid=30006 tid=-99981504  
[ ] BEGIN P9 T4 pid=30063 ppid=30006 tid=-125163776  
[ ] BEGIN P9 T1 pid=30063 ppid=30006 tid=-125163776  
[ ]  END  P9 T1 pid=30063 ppid=30006 tid=-125163776  
[ ] BEGIN P9 T2 pid=30063 ppid=30006 tid=-108378368  
[ ]  END  P9 T4 pid=30063 ppid=30006 tid=-125163776  
[ ]  END  P9 T2 pid=30063 ppid=30006 tid=-108378368  
[ ] BEGIN P9 T3 pid=30063 ppid=30006 tid=-116771072  
[ ]  END  P9 T3 pid=30063 ppid=30006 tid=-116771072  
[ ]  END  P9 T0 pid=30063 ppid=30006 tid=-99981504  
[ ]  END  P1 T0 pid=30006 ppid=3467 tid=-99981504  

Ответы [ 2 ]

0 голосов
/ 23 апреля 2020

Ну, зависит от того, имеет ли значение, когда закончится T13. Вы никогда не сможете знать, как долго будет выполняться поток, так что, в конце концов, не может быть запущено 5 параллельных потоков. Если не имеет значения, когда он закончится, вы можете подсчитайте количество потоков, и когда счетчик достигнет 44, используйте мьютекс в последних 5 потоках.

int threads_running=0
pthread_t thread[49];
pthread_mutex_t lock;
int counter=0;
void *thread(some_args)
{
  if (threads_running==13) while (threads_running <5);

  if(counter==44)
  { 
    pthread_mutex_lock(&lock);
    //do smth
    if(counter==49)
     pthread_mutex_unlock(&lock); 

  }
  else
 {
 //the rest of the threads do smth
  }
}
 int main()
{
  while (counter<49)
   {
     if(threads_running<5)
     { 
       pthread_create(&thread[counter],NULL,thread,thread_arg)
       counter+=1;
       threads_running+=1;
     }
    }

}
0 голосов
/ 23 апреля 2020

Для такого случая было бы полезно семафор ,

с использованием:

  • sem_init для инициализации до желаемого значения
  • sem_post для увеличения значения
  • sem_wait для уменьшения и блокировки, пока значение семафора равно нулю
  • sem_getvalue для получения значения семафора Пример:
void *thread_proc(void* arg) {
   ...
   unbox arg in semaphore and id
   ...
   sem_wait(semaphore);
   // thread is running
   ...
   if(id == 13) { // special case for #13
       unsigned int count=1;
       while(count!=0) {
            sem_getvalue(semaphore,&count);
            pthread_yield();
       }
   }
   sem_post(semaphore);
   return YOUR_RESULT;
}
...
{
    sem_t semaphore;
    sem_init(&semaphore, 0, 5);

    for(int i=0;i<49;++i) {
        ...
        init a new thread and arg with i and semaphore to pass to the thread_proc
        ...

        pthread_create(thread, thread_proc, arg);
    }

Предостережение: не гарантируется, что 5 потоков будут работать одновременно в любой момент времени.

Одно из ожиданий обмана состоит в том, чтобы всегда поддерживать 4 потока "работающим", и позволить одному потоку запускаться и заканчиваться по желанию, пока поток 13 не завершит работу. 4 заблокированный поток будет свободен для продолжения.

...