Могу ли я сигнализировать несколько потоков одновременно с помощью pthread_cond_wait (,)? - PullRequest
0 голосов
/ 16 января 2019

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

Моя текущая проблема состоит в том, что я заставляю их потоки заняты в ожидании. Если количество потоков становится большим, программа значительно замедляется.

Я хотел бы изменить это, используя сигналы, я нашел для этого pthread_cond_wait(), однако я не вижу, как можно использовать это, чтобы сигнализировать всем потокам, что они проснутся.

#include <pthread.h> 
#include <stdio.h> 
#include <unistd.h> 

#define threads 10

int counter=0; 
pthread_mutex_t lock; 

void handler(void *v) {

    pthread_mutex_lock(&lock);  
    counter++;
    printf("%d\n", counter); 
    pthread_mutex_unlock(&lock);   
    while(counter != threads); // busy waiting

    printf("I am first! %d\n", v); 

}


int main() {

    pthread_t t[threads]; 
    for(int i =0; i < threads; i++) {       
    pthread_create(&t[i], NULL, handler, (void*) i); 
    }
    for(int i =0; i < threads; i++) {       
    pthread_join(t[i], NULL); 
    }

    return 0; 
}

РЕДАКТИРОВАТЬ: я изменил код на следующее, однако, он по-прежнему не работает: /

pthread_mutex_t lock; 
pthread_cond_t cv; 

void handler(void *v) {
    pthread_mutex_lock(&lock);
    pthread_cond_wait(&cv, &lock);
    printf("I am first! %d\n", v); 
    pthread_mutex_unlock(&lock);
}


int main() {
    pthread_t t[threads]; 
    for(int i =0; i < threads; i++) 
        pthread_create(&t[i], NULL, handler, (void*) i); 
        sleep(2); 
    pthread_cond_signal(&cv); 
    for(int i =0; i < threads; i++) 
        pthread_join(t[i], NULL); 
    return 0; 
}

Ответы [ 3 ]

0 голосов
/ 16 января 2019

Попробуйте опубликовать соответствующий код remove_from_buffer.

Еще лучше, Короткий, Самодостаточный, Правильный Пример Сделайте короткий main () с двумя потоками. Один поток добавляет в буфер через случайные интервалы. Другой поток удаляет из буфера через произвольные интервалы.

Пример

CELEBP22

/* CELEBP22 */                                   
#define _OPEN_THREADS                                                           
#include <pthread.h>                                                            
#include <stdio.h>                                                              
#include <time.h>                                                               
#include <unistd.h>                                                             

pthread_cond_t cond;                                                            
pthread_mutex_t mutex;                                                          

int footprint = 0;                                                              

void *thread(void *arg) {                                                       
  time_t T;                                                                     

  if (pthread_mutex_lock(&mutex) != 0) {                                        
    perror("pthread_mutex_lock() error");                                       
    exit(6);                                                                    
  }                                                                             
  time(&T);                                                                     
  printf("starting wait at %s", ctime(&T));                                     
  footprint++;                                                                  

  if (pthread_cond_wait(&cond, &mutex) != 0) {                                  
    perror("pthread_cond_timedwait() error");                                   
    exit(7);                                                                    
  }                                                                             
  time(&T);                                                                     
  printf("wait over at %s", ctime(&T));                                         
}                                                                               

main() {                                                                        
  pthread_t thid;                                                               
  time_t T;                                                                     
  struct timespec t;                                                            

  if (pthread_mutex_init(&mutex, NULL) != 0) {                                  
    perror("pthread_mutex_init() error");                                       
    exit(1);                                                                    
  }                                                                             

  if (pthread_cond_init(&cond, NULL) != 0) {                                    
    perror("pthread_cond_init() error");                                        
    exit(2);                                                                    
  }                                                                             

  if (pthread_create(&thid, NULL, thread, NULL) != 0) {                         
    perror("pthread_create() error");                                           
    exit(3);                                                                    
  }                                                                             

  while (footprint == 0)                                                        
    sleep(1);                                                                   

  puts("IPT is about ready to release the thread");                             
  sleep(2);                                                                     

  if (pthread_cond_signal(&cond) != 0) {                                        
    perror("pthread_cond_signal() error");                                      
    exit(4);                                                                    
  }                                                                             

  if (pthread_join(thid, NULL) != 0) {                                          
    perror("pthread_join() error");                                             
    exit(5);                                                                    
  }                                                                             
}       

ВЫХОД

начало ожидания в пт 16 июня 10:54:06 2006 IPT готов освободить ветку ожидания в пятницу 16 июня 10:54:09 2006

0 голосов
/ 18 января 2019

Альтернативным решением для pthread_cond_broadcast() может быть следующее.

Вы определяете мьютекс чтения-записи и блокируете его на запись в основном потоке перед созданием других потоков.Другие потоки попытаются получить блокировку чтения, но поскольку основной поток имеет блокировку записи, они будут заблокированы.

После создания всего потока основной поток снимает блокировку.Все остальные потоки будут активированы, и поскольку многие блокировки чтения могут сосуществовать, они будут выполняться одновременно (то есть никто не будет заблокирован).

Код может выглядеть примерно так:

pthread_rwlock_t lock; 

void handler(void *v) {
    if ((res = pthread_rwlock_rdlock(&lock)!=0)
    {
        exit(1);
    }
    printf("I am first! %d\n", v); 
    pthread_rwlock_unlock(&lock);
}


int main() {
    pthread_t t[threads];
    //First acquire the write lock:
    if ((res = pthread_rwlock_wrlock(&lock)!=0)
    {
        exit(1);
    }        
    for(int i =0; i < threads; i++)
    { 
        pthread_create(&t[i], NULL, handler, (void*) i); 
        //it is not clear if you want sleep inside the loop or not
        // You indented it as if to be inside but not put brackets
        sleep(2); 
    }
    pthread_rwlock_unlock(&lock); 
    for(int i =0; i < threads; i++) 
        pthread_join(t[i], NULL);
    pthread_rwlock_destroy(&lock);
    return 0; 
}
0 голосов
/ 16 января 2019

использовать broadcast()?

http://pubs.opengroup.org/onlinepubs/009696699/functions/pthread_cond_broadcast.html

Функция pthread_cond_broadcast() должна разблокировать все потоки, в настоящее время заблокированные в указанной условной переменной cond.

Функция pthread_cond_signal() должна разблокировать хотя бы один из потоков, которые заблокированы в указанной условной переменной cond (если какие-либо потоки заблокированы в cond).

...