• 四十二、Linux 线程——线程同步之条件变量之线程状态转换


    42.1 线程状态转换

    42.1.1 状态转换图

      

    42.1.2 一个线程计算,多个线程获取的案例

      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <pthread.h>
      4 #include <unistd.h>
      5 
      6 /** 两个线程定义的共享资源 */
      7 typedef struct {
      8     int res;
      9     int counter;            ///< 用于统计获取结果线程的数量
     10     pthread_cond_t cond;    ///< 条件变量
     11     pthread_mutex_t mutex;  ///< 互斥锁
     12 }Result;
     13 
     14 
     15 /** 计算并将结果放置在 Result 中的线程运行函数 */
     16 void *set_fn(void *arg)
     17 {
     18     Result *r = (Result *)arg;
     19     int i = 0;
     20     int sum = 0;
     21 
     22     for(; i <= 100; i++){
     23         sum += i;
     24     }
     25 
     26     /** 将结果放置到 Result 中 */
     27     r->res = sum;
     28 
     29     pthread_mutex_lock(&r->mutex);
     30     /** 判断获取结果的线程是否达到指定的数量 */
     31     while(r->counter < 2){
     32         pthread_mutex_unlock(&r->mutex);
     33         usleep(100);
     34         pthread_mutex_lock(&r->mutex);
     35     }
     36     pthread_mutex_unlock(&r->mutex);
     37 
     38     /** 通知唤醒等待的那个获取结果的线程 */
     39     pthread_cond_broadcast(&r->cond);
     40 
     41     return (void *)0;
     42 }
     43 
     44 /** 获得结果的线程运行函数 */
     45 void *get_fn(void *arg)
     46 {
     47     Result *r = (Result *)arg;
     48 
     49     /** 对两个线程共享的判断条件进行保护(加锁) */
     50     /** 两个线程对判断条件的操作是互斥的 */
     51     pthread_mutex_lock(&r->mutex);
     52     /** 有一个线程准备好了,则计数器 +1 */
     53     r->counter++;
     54 
     55     /** 获取结果的线程等待 */
     56     pthread_cond_wait(&r->cond, &r->mutex);
     57 
     58     /** 被唤醒后 */
     59     pthread_mutex_unlock(&r->mutex);
     60 
     61     /** 去获取计算结果 */
     62     int res = r->res;
     63     printf("0x%lx get sum is %d
    ", pthread_self(), res);
     64 
     65     return (void *)0;
     66 }
     67 
     68 int main(void)
     69 {
     70     int err;
     71     pthread_t cal, get1, get2;
     72 
     73     Result r;
     74     r.counter = 0;
     75     pthread_cond_init(&r.cond, NULL);
     76     pthread_mutex_init(&r.mutex, NULL);
     77 
     78     /** 启动获取结果的线程 */
     79     if((err = pthread_create(&get1, NULL, get_fn, (void *)&r)) != 0){
     80         perror("pthread create error");
     81     }
     82 
     83     if((err = pthread_create(&get2, NULL, get_fn, (void *)&r)) != 0){
     84         perror("pthread create error");
     85     }
     86 
     87     /** 启动计算结果的线程 */
     88     if((err = pthread_create(&cal, NULL, set_fn, (void *)&r)) != 0){
     89         perror("pthread create error");
     90     }
     91 
     92     pthread_join(cal, NULL);
     93     pthread_join(get1, NULL);
     94     pthread_join(get2, NULL);
     95 
     96     pthread_cond_destroy(&r.cond);
     97     pthread_mutex_destroy(&r.mutex);
     98 
     99     pthread_cond_destroy(&r.cond);
    100     pthread_mutex_destroy(&r.mutex);
    101     return 0;
    102 }

      编译运行结果如下:

      

    42.2 读者-写者案例

       

    • 几种情况:
      • 1 个写者,1 个读者
      • 1 个写者,多个读者
      • 多个写者,多个读者

      完成第一种情况:

      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <pthread.h>
      4 #include <string.h>
      5 #include <unistd.h>
      6 
      7 typedef struct {
      8     int             value;
      9 
     10     /** 读者 */
     11     pthread_cond_t  rc;
     12     pthread_mutex_t rm;
     13     int             r_wait;
     14 
     15     /** 写者 */
     16     pthread_cond_t  wc;
     17     pthread_mutex_t wm;
     18     int             w_wait;
     19 }Storage;
     20 
     21 /** 写入数据的函数 */
     22 void set_data(Storage *s, int value)
     23 {
     24     s->value = value;
     25 }
     26 
     27 /** 获取数据的函数 */
     28 int get_data(Storage *s)
     29 {
     30     return s->value;
     31 }
     32 
     33 /** 写者线程运行函数定义 */
     34 void *set_th(void *arg)
     35 {
     36     Storage *s = (Storage *)arg;
     37     int i = 1;
     38     for(; i <= 100; i++){
     39         /** 写入数据 */
     40         set_data(s, i +100);
     41         printf("0x%lx(%-5d) write data : %d
    ", pthread_self(), i, i + 100);
     42 
     43         pthread_mutex_lock(&s->rm);
     44         /** 判断读者线程是否准备好 */
     45         while(!s->r_wait){
     46             pthread_mutex_unlock(&s->rm);
     47             sleep(1);
     48             pthread_mutex_lock(&s->rm);
     49         }
     50         s->r_wait = 0;
     51         pthread_mutex_unlock(&s->rm);
     52 
     53         /** 通知读者线程读取数据 */
     54         pthread_cond_broadcast(&s->rc);
     55 
     56         /** 写者线程自阻塞等待读者线程通知已经读取完毕,
     57          * 然后唤醒写者线程继续写入数据 */
     58         pthread_mutex_lock(&s->wm);
     59         s->w_wait = 1;
     60         pthread_cond_wait(&s->wc, &s->wm);
     61         pthread_mutex_unlock(&s->wm);
     62 
     63     }
     64     return (void *)0;
     65 }
     66 
     67 /** 读者线程运行函数定义 */
     68 void *get_th(void *arg)
     69 {
     70     Storage *s = (Storage *)arg;
     71     int i = 1;
     72     for(; i <= 100; i++){
     73         pthread_mutex_lock(&s->rm);
     74         s->r_wait = 1;
     75         pthread_cond_wait(&s->rc, &s->rm);
     76         pthread_mutex_unlock(&s->rm);
     77 
     78         /** 读者线程被唤醒后读取数据 */
     79         int value = get_data(s);
     80         printf("0x%lx(%-5d) read data: %d
    ", pthread_self(), i, value);
     81 
     82         pthread_mutex_lock(&s->wm);
     83         /** 判断写者线程是否准备好 */
     84         while(!s->w_wait){
     85             pthread_mutex_unlock(&s->wm);
     86             sleep(1);
     87             pthread_mutex_lock(&s->wm);
     88         }
     89         /** 唤醒写者线程 */
     90         s->w_wait = 0;
     91         pthread_mutex_unlock(&s->wm);
     92         pthread_cond_broadcast(&s->wc);
     93 
     94     }
     95     return (void *)0;
     96 }
     97 
     98 int main(void)
     99 {
    100     int err;
    101     pthread_t   rth, wth;
    102 
    103     Storage s;
    104     s.r_wait = 0;
    105     s.w_wait = 0;
    106     pthread_mutex_init(&s.rm, NULL);
    107     pthread_mutex_init(&s.wm, NULL);
    108     pthread_cond_init(&s.rc, NULL);
    109     pthread_cond_init(&s.wc, NULL);
    110 
    111     /** 创建一个读者线程和写者线程 */
    112     if((err = pthread_create(&rth, NULL, get_th, (void *)&s)) != 0){
    113         perror("pthread create error");
    114     }
    115 
    116     if((err = pthread_create(&wth, NULL, set_th, (void *)&s)) != 0){
    117         perror("pthread create error");
    118     }
    119 
    120     pthread_join(rth, NULL);
    121     pthread_join(wth, NULL);
    122 
    123     pthread_mutex_destroy(&s.rm);
    124     pthread_mutex_destroy(&s.wm);
    125     pthread_cond_destroy(&s.rc);
    126     pthread_cond_destroy(&s.wc);
    127 
    128     return 0;
    129 }
  • 相关阅读:
    Android拷贝工程不覆盖原工程的配置方法
    Android中BindService方式使用的理解
    getApplicationContext()、Activity.this、 getBaseContext区别
    深入理解ASP.NET MVC(4)
    深入理解ASP.NET MVC(1)
    深入理解ASP.NET MVC(2)
    深入理解ASP.NET MVC(目录)
    C# 代码优化
    NPOI 创建Excel 设置宽度 样式 颜色对比表
    2. Mysql数据库的入门知识
  • 原文地址:https://www.cnblogs.com/kele-dad/p/10263781.html
Copyright © 2020-2023  润新知