线程同步3

使用条件变量进行线程同步

1
2
3
4
5
6
7
#include <pthread.h>
int pthread_cond_init(pthread_cond_t *restrict cond;
                                   const pthread_condattr_t *restrict attr);
int pthread_cond_destroy(pthread_cond_t *cond);
int pthread_cond_wait(pthread_cond_t *restrict cond,
                                     pthread_mutex_t *restrict mutex,
                                     const struct timespec *restrict tsptr);
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
 // APUE example 11-15                             
 // using mutex and cond                           
 // lcl 20190326                                   
 //                                                
 #include "../myapue/h"                            
 #include <pthread.h>                              

 struct msg{                                       
     struct msg * m_next;                          
     /* ...*/                                      
 };                                                

 struct msg *workq;                                
 pthread_cond_t qready = PTHREAD_COND_INITIALIZER;
 pthread_mutex_t qlock = PTHREAD_MUTEX_INITIALIZER;

 void process_mag(void)                            
 {                                                 
     struct msg *mp;                               
     for(;;)                                       
     {                                             
         pthread_mutex_lock(&qlock);               
         while(workq == NULL)                      
           pthread_cond_wait(&qready, &qlock);     
         mp = workq;                               
         workq = mp -> m_next;                     
         phread_mutex_unlock(&qlock);              
         /* noe process msg */                     
     }                                             
 }                                                 
 void enqueue_msg(struct msg *mp)                  
 {                                                 
     pthread_mutex_lock(&qlock);                   
     mp->m_next = workq;                           
     workq = mp;                                   
     pthread_mutex_unlock(&qlock);                 
     pthread_cond_signal(&qready);                 
 }                                                 

barrier,屏障

1
2
3
4
5
int pthread_barrier_init(pthread_barrier_t *restrict barrier,
            const pthread_barrierattr_t *restrict attr,      
            unsigned int count);                             
int pthrerd_barrier_destroy(pthread_barrier_t *barrier);     
int pthread_barrier_wait(pthread_barruer_t *barrier);        
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
/* APUE example 11-16                            
 * using barrier                                 
 * lcl 20190326                                  
 *                                               
 */                                              

#include "../myapue.h"                           
#include <pthread.h>                             
#include <limits.h>                              
#include <sys/time.h>                            

#define NTHR 8                                   
#define NUMNUM 8000000L                          
#define TNUM (NUMNUM/NTHR)                       

long nums[NUMNUM];                               
long snums[NUMNUM];                              

pthread_barrier_t b;                             

//extern int qsort(void *, size_t, size_t,       
//          int (*)(const void*, const void *));

int complong(const void *arg1, const void *arg2)
{                                                
    long l1 = *(long *)arg1;                     
    long l2 = *(long *)arg2;                     

    if (l1 == l2)                                
      return 0;                                  
    else if (l1 <l2)                             
        return -1;                               
    else return 1;                               
}                                                

 void *thr_fn(void *arg)                         
{                                                
    long idx = (long)arg;                                       

    qsort(&nums[idx], TNUM, sizeof(long), complong);            
    pthread_barrier_wait(&b);                                   
    return ((void*)0);                                          
}                                                               

void merge()                                                    
{                                                               
    long idx[NTHR];                                             
    long i,minidx, sidx, num;                                   

    for (i = 0;i<NTHR; i++)                                     
      idx[i] = i*TNUM;                                          
    for (sidx = 0;sidx < NUMNUM; sidx++){                       
        num = LONG_MAX;                                         
        for (i = 0; i<NTHR; i++){                               
            if( (idx[i] < (i+1)*TNUM) && (nums[idx[i]] < num)){
                num = nums[idx[i]];                             
                minidx = i;                                     
            }                                                   
        }                                                       
        snums[sidx] = nums[idx[minidx]];                        
        idx[minidx]++;                                          
    }                                                           
}                                                               

int main()                                                      
{                                                               
    unsigned long i;                                            
    struct timeval start,end;                                   
    long long startusec, endusec;                               
    double elapsed;                                             
    int err;                                                    
    pthread_t tid;                                              

    // create the initial set of numbers to sort.               
    srandom(1);                                                 
    for(i=0; i<NUMNUM; i++) {                                   
        nums[i] = random();                                     
    }                                                           

    // create 8 threads to sort the numbers                     
    gettimeofday(&start,NULL);                                  
    pthread_barrier_init(&b, NULL, NTHR+1);                     
    for (i=0; i<NTHR; i++)                                      
    {                                                           
        err = pthread_create(&tid,NULL,thr_fn,(void *)(i*TNUM));
        if(err!=0)                                              
          printf("can't create thread");                        
    }                                                           
    pthread_barrier_wait(&b);                                   
    merge();                                                    
    gettimeofday(&end,NULL);                                    

    startusec = start.tv_sec * 1000000 + start.tv_usec;         

    endusec = end.tv_sec * 1000000 + end.tv_usec;               
    elapsed = (double)(endusec - startusec)/1000000.0;          
    printf("sort using %.4f seconds\n",elapsed);                
    for(i=0;i<100;i++)                                          
      printf("%ld\n",snums[i]);                                 
    exit(0);                                                    
}