Linux互斥与同步应用(三):posix线程实现单个生产者和单个消费者模型

【版权声明:尊重原创,转载请保留出处:blog.csdn.net/shallnet 或 .../gentleliu,文章仅供学习交流,请勿用于商业用途】

在第一节说到了生产者消费者问题,这一节我们来实现这样一个稍作修改的模型: 初始时缓冲区为空,生产者向缓冲区写入数据,消费者在缓冲区为空的情况下睡眠,当生产者写满缓冲区一半之后后通知消费者可以开始消费,生产者开始睡眠,直到消费者消费完缓冲区一半后通知生产者可以开始生产为止,其中生产者和消费者对缓冲区的访问时互斥的。

下面来看一下实现:

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

#define MAX_BUFFER 6

int buffer = 0;

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond_consumer = PTHREAD_COND_INITIALIZER;
pthread_cond_t cond_productor = PTHREAD_COND_INITIALIZER;

void *consumer_th(void *arg)
{

    for (;;) {
        pthread_mutex_lock(&mutex);

        if (buffer <= 0) {
            printf("=%s->%d=====consumer wait productor to product, start sleep..., buffer=%d\n", __func__, __LINE__, buffer);
            pthread_cond_wait(&cond_consumer, &mutex);//当消费者发现缓冲区为空时开始睡眠
        }

        buffer--; //消费者消耗一个缓冲区
        printf("=%s->%d====consumer consume a buffer, buffer=%d\n", __func__, __LINE__, buffer);
        if (buffer < MAX_BUFFER/2) {
            pthread_cond_signal(&cond_productor); //当消费者发现缓冲区不足一半时通知生产者开始生产
            printf("=%s->%d====Notify productor...,, buffer: %d\n", __func__, __LINE__, buffer);
        }

        pthread_mutex_unlock(&mutex);

        sleep(3);
    }

    return NULL;
}

void *productor_th(void *arg)
{

    for (;;) {
        sleep(1);

        pthread_mutex_lock(&mutex);

        if (buffer >= MAX_BUFFER) {
            printf("=%s->%d=====productor wait consumer to consume, start sleep..., buffer=%d\n", __func__, __LINE__, buffer);
            pthread_cond_wait(&cond_productor, &mutex);//当缓冲区满时,暂停生产
        }

        buffer++;//生产者增加一个缓冲区
        printf("=%s->%d====Product add a buffer..., buffer: %d\n", __func__, __LINE__, buffer);

        if (buffer > MAX_BUFFER/2) {
            pthread_cond_signal(&cond_consumer);//当缓冲区增加到一半时,通知消费者可以开始消费
            printf("=%s->%d====Notify consumer...,, buffer: %d\n", __func__, __LINE__, buffer);
        }

        pthread_mutex_unlock(&mutex);
    }
    return NULL;
}

int main(int argc, const char *argv[])
{
    pthread_t tid_productor, tid_consumer;

    if (0 != pthread_create(&tid_consumer, NULL, consumer_th, NULL)) {
        printf("pthread_create failed!\n");
        return -1;
    }

    if (0 != pthread_create(&tid_productor, NULL, productor_th, NULL)) {
        printf("pthread_create failed!\n");
        return -1;
    }

    pthread_join(tid_productor, NULL);
    pthread_join(tid_consumer, NULL);

    return 0;
}

下面是程序运行输出结果:

=consumer_th->20=====consumer wait productor to product, start sleep..., buffer=0//消费者开始睡眠等待生产者唤醒
=productor_th->54====Product add a buffer..., buffer: 1
=productor_th->54====Product add a buffer..., buffer: 2
=productor_th->54====Product add a buffer..., buffer: 3
=productor_th->54====Product add a buffer..., buffer: 4//生产者开始写缓冲区,当写到第4(超过一半)个通知消费者
=productor_th->58====Notify consumer...,, buffer: 4
=consumer_th->25====consumer consume a buffer, buffer=3//消费者一边消费缓冲区
=productor_th->54====Product add a buffer..., buffer: 4//生产者一边生产缓冲区
=productor_th->58====Notify consumer...,, buffer: 4
=productor_th->54====Product add a buffer..., buffer: 5
=productor_th->58====Notify consumer...,, buffer: 5
=consumer_th->25====consumer consume a buffer, buffer=4
=productor_th->54====Product add a buffer..., buffer: 5
=productor_th->58====Notify consumer...,, buffer: 5
=productor_th->54====Product add a buffer..., buffer: 6
=productor_th->58====Notify consumer...,, buffer: 6
=productor_th->49=====productor wait consumer to consume, start sleep..., buffer=6//当生产者生产缓冲区满时,开始睡眠
=consumer_th->25====consumer consume a buffer, buffer=5
=consumer_th->25====consumer consume a buffer, buffer=4
=consumer_th->25====consumer consume a buffer, buffer=3
=consumer_th->25====consumer consume a buffer, buffer=2//当消费者消费缓冲区到不足一半时,唤醒生产者开始生产
=consumer_th->28====Notify productor...,, buffer: 2
=productor_th->54====Product add a buffer..., buffer: 3
=productor_th->54====Product add a buffer..., buffer: 4
=productor_th->58====Notify consumer...,, buffer: 4
=productor_th->54====Product add a buffer..., buffer: 5
=productor_th->58====Notify consumer...,, buffer: 5
=consumer_th->25====consumer consume a buffer, buffer=4
=productor_th->54====Product add a buffer..., buffer: 5
=productor_th->58====Notify consumer...,, buffer: 5
=productor_th->54====Product add a buffer..., buffer: 6
=productor_th->58====Notify consumer...,, buffer: 6
=productor_th->49=====productor wait consumer to consume, start sleep..., buffer=6

本节源码下载:

点击打开链接

时间: 2024-10-19 16:08:57

Linux互斥与同步应用(三):posix线程实现单个生产者和单个消费者模型的相关文章

多个生产者——多个消费者模型(互斥量条件变量实现)

1. 介绍 生产者消费者问题属于有界缓冲区问题.我们现在讲述多个生产者向一个缓冲区中存入数据,多个生产者从缓冲区中取数据. 共享缓冲区作为一个环绕缓冲区,存数据到头时再从头开始. 2. 实现 我们使用一个互斥量保护生产者向缓冲区中存入数据. 由于有多个生产者,因此需要记住现在向缓冲区中存入的位置. 使用一个互斥量保护缓冲区中消息的数目,这个生产的数据数目作为生产者和消费者沟通的桥梁. 使用一个条件变量用于唤醒消费者.由于有多个消费者,同样消费者也需要记住每次取的位置. 4.代码 在选项中选择生产

Linux互斥与同步应用(四):posix信号量的互斥与同步

[版权声明:尊重原创,转载请保留出处:blog.csdn.net/shallnet 或 .../gentleliu,文章仅供学习交流,请勿用于商业用途] 在前面讲共享内存的IPC时曾说共享内存本身不具备同步机制,如果要实现同步需要使用信号量等手段来实现之,现在我们就来说说使用posix的信号量来实现posix多进程共享内存的同步.其实信号量也可以使用在同一进程的不同线程之间. 信号量是一个包含非负整数的变量,有两个原子操作,wait和post,也可以说是P操作和V操作,P操作将信号量减一,V操作

Linux下用环形buf以及POSIX版本信号量解决生产者消费者问题

一.Semaphore(信号量) Mutex变量是非0即1的,可看作一种资源的可用数量,初始化时Mutex是1,表示有一个可用资源, 加锁时获得该资源,将Mutex减到0,表示不再有可用资源,解锁时释放该资源,将Mutex重新加到1,表示又有了一个可用资源. 信号量(Semaphore)和Mutex类似,表示可用资源的数量,和Mutex不同的是这个数量可以大于1. 即,如果信号量描述的资源数目是1时,此时的信号量和互斥锁相同! 本次使用的是POSIX semaphore库函数,这种信号量不仅可以

Linux互斥与同步应用(一):posix线程及线程间互斥

[版权声明:尊重原创,转载请保留出处:blog.csdn.net/shallnet 或 .../gentleliu,文章仅供学习交流,请勿用于商业用途] 有了进程的概念,为何还要使用线程呢? 首先,回忆一下上一个系列我们讲到的IPC,各个进程之间具有独立的内存空间,要进行数据的传递只能通过通信的方式进行,这种方式不仅费时,而且很不方便.而同一个进程下的线程是共享全局内存的,所以一个线程的数据可以在另一个线程中直接使用,及快捷又方便. 其次,在Linux系统下,启动一个新的进程必须分配给它独立的地

Linux互斥与同步应用(二):posix线程同步

[版权声明:尊重原创,转载请保留出处:blog.csdn.net/shallnet 或 .../gentleliu,文章仅供学习交流,请勿用于商业用途] 上一节说到线程的互斥锁,互斥锁适合防止访问某个共享变量,这一节我们来看看两个线程如何实现同步.互斥锁也可以实现线程同步,当该值满足某种条件时当前线程继续执行,否则继续轮询,不过这样相当浪费cpu时间.我们需要的是让某个线程进入睡眠,当满足该线程执行条件时,另外线程主动通知它,这就是这一节我们要说的条件变量,它常和互斥锁一起使用. 如同信号量,线

Linux相互排斥与同步应用(三):posix线程实现单个生产者和单个消费者模型

[版权声明:尊重原创.转载请保留出处:blog.csdn.net/shallnet 或 .../gentleliu.文章仅供学习交流,请勿用于商业用途] 在第一节说到了生产者消费者问题,这一节我们来实现这样一个稍作改动的模型: 初始时缓冲区为空.生产者向缓冲区写入数据.消费者在缓冲区为空的情况下睡眠,当生产者写满缓冲区一半之后后通知消费者能够開始消费.生产者開始睡眠.直到消费者消费完缓冲区一半后通知生产者能够開始生产为止,当中生产者和消费者对缓冲区的訪问时相互排斥的. 以下来看一下实现: #in

Linux互斥与同步应用(六):文件锁

[版权声明:尊重原创,转载请保留出处:blog.csdn.net/shallnet 或 .../gentleliu,文章仅供学习交流,请勿用于商业用途] 当一个系统中存在多个进程同时操作同一个文件时,为了保证数据的正确, 一般会将文件上锁来避免共享文件产生的竞争状态.在linux系统下文件上锁可以使用fcntl函数来实现. 函数fcntl原型如下: #include <unistd.h> #include <fcntl.h> int fcntl(int fd, int cmd, .

Linux互斥与同步应用(五):system V信号量的互斥与同步

[版权声明:尊重原创,转载请保留出处:blog.csdn.net/shallnet 或 .../gentleliu,文章仅供学习交流,请勿用于商业用途] system V信号量操作类似于posix信号量,但system V信号量的操作要复杂得多,posix信号量使用步骤为sem_init(sem_open)-->sem_wait(sem_post) --> sem_close详见上一节,system V使用不同的函数. 1. 创建和打开信号量函数:semget(). #include <

【Linux 线程】线程同步《三》

1.条件变量 条件变量是利用线程间共享的全局变量进行同步的一种机制,主要包括两个动作:一个线程等待"条件变量的条件成立"而挂起:另一个线程使"条件成立"(给出条件成立信号).为了防止竞争,条件变量的使用总是和一个互斥 (1)创建和注销   条件变量和互斥锁一样,都有静态&动态两种创建方式,静态方式使用PTHREAD_COND_INITIALIZER常量,如下:       pthread_cond_t   cond=PTHREAD_COND_INITIALI