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

时间:2022-09-03 19:12:24
  • 同步

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

  • 互斥

对一组并发进程,一次只有一个进程能够访问一个给定的资源或执行一个给定的功能。
互斥技术可以用于解决诸如资源争用之类的冲突,还可以用于进程间的同步,使得它们可以合作。典型例子便是生产者/消费者模型。
  • 同步互斥的实现思路主要有两种:
  • 软件方法(这里讲的)
  • 信号量
  • 使用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算法是一个实现互斥的并发程序设计算法
  • Linux同步互斥(Peterson算法,生产者消费者模型)
  • 临界缓冲区问题描述

有一个或者多个生产者产生某种类型的数据(记录、字符),并放置在缓冲区中;有一个消费者从缓冲区中取数据,每次取一项;系统保证避免对缓冲区的重复操作,也就是说,在任何时候只有一个代理(生产者或者消费者)可以访问缓冲区。
 
  • 生产者消费者模型(C代码)
  • //thread.c
    1 #include <stdio.h>
    #include <pthread.h>
    #define MAX 10 //需要生产的数量
    pthread_mutex_t the_mutex; //互斥锁
    pthread_cond_t condc, condp; //条件变量
    int buffer = ;//生产者、消费者使用的缓冲区 void *producer(void *ptr)
    {
    int i;
    for(i=; i<=; i++)
    {
    pthread_mutex_lock(&the_mutex); //互斥使用缓冲区
    while(buffer !=) pthread_cond_wait(&condp, &the_mutex); //阻塞等待
    printf("procucer produce item %d\n",i);
    buffer = i; //生产产品
    pthread_cond_signal(&condc);//通知消费者消费
    pthread_mutex_unlock(&the_mutex);//释放缓冲区
    } pthread_exit(); } void *consumer(void *ptr)
    { int i;
    for(i=; i<=; i++)
    {
    pthread_mutex_lock(&the_mutex);//互斥使用缓冲区
    while(buffer ==) pthread_cond_wait(&condc, &the_mutex); //阻塞等待
    printf("consumer consume item %d\n",i);
    buffer = ;//清空缓存区
    pthread_cond_signal(&condp);//通知生产者生产产品
    pthread_mutex_unlock(&the_mutex);//释放缓冲区
    }
    pthread_exit(); } int main(int argc, char *argv[])
    {
    pthread_t pro, con; pthread_mutex_init(&the_mutex, ); //创建互斥锁
    pthread_cond_init(&condc,); //初始化条件变量
    pthread_cond_init(&condp,); pthread_create(&con, , consumer, );
    pthread_create(&pro, , producer, );
    pthread_join(pro,);
    pthread_join(con,);
    pthread_cond_destroy(&condc);
    pthread_cond_destroy(&condp);
    pthread_mutex_destroy(&the_mutex);
    return ;
    }

    输出:

  • procucer produce item
    consumer consume item
    procucer produce item
    consumer consume item
    procucer produce item
    consumer consume item
    procucer produce item
    consumer consume item
    procucer produce item
    consumer consume item
    procucer produce item
    consumer consume item
    procucer produce item
    consumer consume item
    procucer produce item
    consumer consume item
    procucer produce item
    consumer consume item
    procucer produce item
    consumer consume item

    注意:

  • 在编译中要加 -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是指向一个条件变量的指针