Linux同步互斥(Peterson算法,生产者消费者模型)

  • 同步

两个或两个以上随时间变化的量在变化过程中保持一定的相对关系。

  • 互斥

对一组并发进程,一次只有一个进程能够访问一个给定的资源或执行一个给定的功能。
互斥技术可以用于解决诸如资源争用之类的冲突,还可以用于进程间的同步,使得它们可以合作。典型例子便是生产者/消费者模型。
  • 同步互斥的实现思路主要有两种:
  • 软件方法(这里讲的)
  • 信号量
  • 使用POSIX线程库(pthread_),来创建线程,管理线程,实现同步互斥。

  • POSIX(可移植操作系统)线程是线程的POSIX标准,定义了创建和操作线程的一套API。
  • 可用于多线程编程
  • POSIX线程库函数—介绍将会用到的

  • int pthread_create(pthread_t *thread, pthread_attr_t *attr,void *(*start_routine)(void *), void *arg);
  •作用:创建一个线程
  •参数thread:如果创建线程成功,标识本线程的唯一标识符通过本变量返回给函数调用者;
  •参数attr:调用者通过该参数描述期望创建的线程具有什么样的属性,传入NULL表示使用默认属性;
  •参数start_routine:线程的运行实体;
  •参数arg:传递给线程实体的参数;
  •返回值:0成功,非0为错误码;
 
  • int pthread_join(pthread_t th, void **thread_return);
  •作用:等待一个线程结束,以阻塞的方式等待th指定的线程结束。
  •参数th:描述等待一个线程结束,其取值为pthread_create函数第一个参数的返回值;
  •参数thread_return:被等待线程结束时的返回值,用户定义的指针,用来存储被等待线程的返回值。
 
  • Peterson算法

  • Peterson算法是一个实现互斥的并发程序设计算法
  • 临界缓冲区问题描述

有一个或者多个生产者产生某种类型的数据(记录、字符),并放置在缓冲区中;有一个消费者从缓冲区中取数据,每次取一项;系统保证避免对缓冲区的重复操作,也就是说,在任何时候只有一个代理(生产者或者消费者)可以访问缓冲区。
 
  • 生产者消费者模型(C代码)
  • //thread.c
    1
    #include <stdio.h> 2 #include <pthread.h> 3 #define MAX 10 //需要生产的数量 4 pthread_mutex_t the_mutex; //互斥锁 5 pthread_cond_t condc, condp; //条件变量 6 int buffer = 0;//生产者、消费者使用的缓冲区 7 8 void *producer(void *ptr) 9 { 10 int i; 11 for(i=1; i<=10; i++) 12 { 13 pthread_mutex_lock(&the_mutex); //互斥使用缓冲区 14 while(buffer !=0) pthread_cond_wait(&condp, &the_mutex); //阻塞等待 15 printf("procucer produce item %d ",i); 16 buffer = i; //生产产品 17 pthread_cond_signal(&condc);//通知消费者消费 18 pthread_mutex_unlock(&the_mutex);//释放缓冲区 19 } 20 21 pthread_exit(0); 22 23 } 24 25 void *consumer(void *ptr) 26 { 27 28 int i; 29 for(i=1; i<=10; i++) 30 { 31 pthread_mutex_lock(&the_mutex);//互斥使用缓冲区 32 while(buffer ==0) pthread_cond_wait(&condc, &the_mutex); //阻塞等待 33 printf("consumer consume item %d ",i); 34 buffer = 0;//清空缓存区 35 pthread_cond_signal(&condp);//通知生产者生产产品 36 pthread_mutex_unlock(&the_mutex);//释放缓冲区 37 } 38 pthread_exit(0); 39 40 } 41 42 int main(int argc, char *argv[]) 43 { 44 pthread_t pro, con; 45 46 pthread_mutex_init(&the_mutex, 0); //创建互斥锁 47 pthread_cond_init(&condc,0); //初始化条件变量 48 pthread_cond_init(&condp,0); 49 50 pthread_create(&con, 0, consumer, 0); 51 pthread_create(&pro, 0, producer, 0); 52 pthread_join(pro,0); 53 pthread_join(con,0); 54 pthread_cond_destroy(&condc); 55 pthread_cond_destroy(&condp); 56 pthread_mutex_destroy(&the_mutex); 57 return 0; 58 }

    输出:

  • procucer produce item 1
    consumer consume item 1
    procucer produce item 2
    consumer consume item 2
    procucer produce item 3
    consumer consume item 3
    procucer produce item 4
    consumer consume item 4
    procucer produce item 5
    consumer consume item 5
    procucer produce item 6
    consumer consume item 6
    procucer produce item 7
    consumer consume item 7
    procucer produce item 8
    consumer consume item 8
    procucer produce item 9
    consumer consume item 9
    procucer produce item 10
    consumer consume item 10

    注意:

  • 在编译中要加 -lpthread参数, 如:gcc thread.c -o thread –lpthread
  • 使用到的一些函数功能介绍
  • int pthread_cond_wait(pthread_cond_t  *cond,  pthread_mutex_t   *mutex)

    作用:互斥的条件等待,阻塞线程

    参数:*cond是指向一个条件变量的指针

      *mutex则是对相关的互斥锁的指针

  • int pthread_cond_signal(pthread_cond_t *cond)

    作用:发送一个信号给另外一个正在处于阻塞等待状态的线程,使其脱离阻塞状态,继续执行

    参数:*cond是指向一个条件变量的指针

原文地址:https://www.cnblogs.com/dear_diary/p/6051481.html