Can I signal multiple threads simultaneously with

2019-09-20 22:57发布

I am writing various code snippets and see what happens. The code below was intended to delay all threads until all reached a certain point in the code and then make each print a distinctive number. Since the threads all do that, the numbers should occur in a random order.

My current problem is that I keep they threads busy waiting. If the number of threads gets big, the program slows down significantly.

I would like to change that by using signals, I found pthread_cond_wait() for that, however I don't see how one would use that to signal all threads that they would please wake up.

#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; 
}

EDIT: I changed the code to the following, however, it still does not work :/

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条回答
做个烂人
2楼-- · 2019-09-20 23:07

use broadcast()?

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

The pthread_cond_broadcast() function shall unblock all threads currently blocked on the specified condition variable cond.

The pthread_cond_signal() function shall unblock at least one of the threads that are blocked on the specified condition variable cond (if any threads are blocked on cond).

查看更多
我想做一个坏孩纸
3楼-- · 2019-09-20 23:08

Try posting the matching remove_from_buffer code.

Better yet, Short, Self Contained, Correct Example Make a short main() with two threads. One thread adds to the buffer at random intervals. The other thread removes from the buffer at random intervals.

Example

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);                                                                    
  }                                                                             
}       

OUTPUT

starting wait at Fri Jun 16 10:54:06 2006 IPT is about ready to release the thread wait over at Fri Jun 16 10:54:09 2006

查看更多
甜甜的少女心
4楼-- · 2019-09-20 23:25

An alternative solution to pthread_cond_broadcast() might be the following.

You define a read-write mutex and lock it in write in the main thread before creating the other threads. The other threads will try to acquire a read-lock but since the main thread have a write-lock they will be blocked.

After the creation of all thread the main-thread releases the lock. All the other threads will be waken up and since many read-locks can coexist the will execute simultaneously (i.e. no one will be locked).

Code might be something like:

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; 
}
查看更多
登录 后发表回答