pthredd_cond_wait

  1. #include <pthread.h>  
  2. #include <unistd.h>  
  3.   
  4. static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;  
  5. static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;  
  6.   
  7. struct node {  
  8. int n_number;  
  9. struct node *n_next;  
  10. } *head = NULL;  
  11.   
  12. /*[thread_func]*/  
  13. static void cleanup_handler(void *arg)  
  14. {  
  15.     printf("Cleanup handler of second thread./n");  
  16.     free(arg);  
  17.     (void)pthread_mutex_unlock(&mtx);  
  18. }  
  19. static void *thread_func(void *arg)  
  20. {  
  21.     struct node *p = NULL;  
  22.   
  23.     pthread_cleanup_push(cleanup_handler, p);  // 防止在获取锁之后,程序崩溃,引起的锁没有释放。加上这个之后,崩溃会调用到cleanup_handler
  24.     while (1) {  
  25.     pthread_mutex_lock(&mtx);           //这个mutex主要是用来保证pthread_cond_wait的并发性  
  26.     while (head == NULL)   {               //这个while要特别说明一下,单个pthread_cond_wait功能很完善,为何这里要有一个while (head == NULL)呢?因为有多个线程在等待被唤醒的时候,也就是在生产者线程里调用pthread_cond_signal,会从pthread_cond_wait开始执行,但是只有一个线程可以获取到资源,同时获取到锁。在执行线程里消耗完资源的时候,别的等待线程也从pthread_cond_wait之后执行,再次判断资源是否符合条件(因为已经消耗了,必定不符合),所以可以继续等待资源。
  27.         pthread_cond_wait(&cond, &mtx);         // pthread_cond_wait会先解除之前的pthread_mutex_lock锁定的mtx,然后阻塞在等待对列里休眠,直到再次被唤醒(大多数情况下是等待的条件成立而被唤醒,唤醒后,该进程会先锁定先pthread_mutex_lock(&mtx);,再读取资源  
  28.                                                 //用这个流程是比较清楚的/*block-->unlock-->wait() return-->lock*/  
  29.     }  
  30.         p = head;  
  31.         head = head->n_next;  
  32.         printf("Got %d from front of queue/n", p->n_number);  
  33.         free(p);  
  34.         pthread_mutex_unlock(&mtx);             //临界区数据操作完毕,释放互斥锁  
  35.     }  
  36.     pthread_cleanup_pop(0);  
  37.     return 0;  
  38. }  
  39.   
  40. int main(void)  
  41. {  
  42.     pthread_t tid;  
  43.     int i;  
  44.     struct node *p;  
  45.     pthread_create(&tid, NULL, thread_func, NULL);   //子线程会一直等待资源,类似生产者和消费者,但是这里的消费者可以是多个消费者,而不仅仅支持普通的单个消费者,这个模型虽然简单,但是很强大  
  46.     /*[tx6-main]*/  
  47.     for (i = 0; i < 10; i++) {  
  48.         p = malloc(sizeof(struct node));  
  49.         p->n_number = i;  
  50.         pthread_mutex_lock(&mtx);             //需要操作head这个临界资源,先加锁,  
  51.         p->n_next = head;  
  52.         head = p;  
  53.         pthread_cond_signal(&cond);  //pthread_cond_signal应该写在锁里边,如果写在锁外边的话,可能会有别的线程抢占到锁。但是,也有这种情况,就是pthread_cond_wait唤醒,获取锁,发现pthread_cond_signal还没有释放锁,进而继续进入休眠状态。需要测试
  54.         pthread_mutex_unlock(&mtx);           //解锁  
  55.         sleep(1);  
  56.     }  
  57.     printf("thread 1 wanna end the line.So cancel thread 2./n");  
  58.     pthread_cancel(tid);             //
  59.     pthread_join(tid, NULL);  
  60.     printf("All done -- exiting/n");  
  61.     return 0;  
  62. }  
posted @ 2018-08-20 21:17  caopf  阅读(82)  评论(5编辑  收藏  举报