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-12 00:18:07

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

Linux环境编程之同步(四):Posix信号量

信号量是一种用于提供不同进程间或一个给定进程的不同线程间同步手段的原语.有三种类型:Posix有名信号量,使用Posix IPC名字标识:Posix基于内存的信号量,存放在共享内存区中:System V信号量,在内核中维护.这三种信号量都可用于进程间或线程间的同步. 图1 由两个进程使用的一个二值信号量 图2 由两个进程使用的一个Posix有名二值信号量 图3 由一个进程内的两个线程共享的基于内存的信号量 一个进程可以在某个信号量上执行的三种操作: 1.创建一个信号量,这要求调用者指定初始值,对

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

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

Linux多线程同步之相互排斥量和条件变量

1. 什么是相互排斥量 相互排斥量从本质上说是一把锁,在訪问共享资源前对相互排斥量进行加锁,在訪问完毕后释放相互排斥量上的锁. 对相互排斥量进行加锁以后,不论什么其它试图再次对相互排斥量加锁的线程将会被堵塞直到当前线程释放该相互排斥锁.假设释放相互排斥锁时有多个线程堵塞,所以在该相互排斥锁上的堵塞线程都会变成可进行状态.第一个变成执行状态的线程能够对相互排斥量加锁.其它线程在次被堵塞,等待下次执行状态. pthread_mutex_t 就是POSIX对于mutex的实现. 函数名 參数 说明 p

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

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

深入理解相互排斥锁的实现

在实际的软件编程中,常常会遇到资源的争用,比方以下的样例: [cpp] view plaincopyprint? class Counter { private: int value; public: Counter(int c) { value = c; } int GetAndIncrement() { int temp = value; //进入危急区 value = temp +1; //离开危急区 return value; } } class Counter { private: i

POSIX 线程具体解释(3-相互排斥量:&quot;固定加锁层次&quot;/“试加锁-回退”)

有时一个相互排斥量是不够的: 比方: 当多个线程同一时候訪问一个队列结构时,你须要2个相互排斥量,一个用来保护队列头,一个用来保护队列元素内的数据. 当为多线程建立一个树结构时.你可能须要为每一个节点设置一个相互排斥量. 同一时候使用多个相互排斥量会导致复杂度的添加 最坏的情况就是死锁的发生.即两个线程分别锁住一个相互排斥量而等待对方的相互排斥量. 多相互排斥量可能导致死锁: 假设能够在独立的数据上使用两个分离的相互排斥量,那么就应该这么做. 这样,通过降低线程必须等待其它线程完毕数据操作的时间

线程同步和互斥(条件变量控制生产者消费者模型)

条件变量 生产者消费者模型: 关系:      同步 生产者<----->消费者    互斥 互斥 生产者<----->生产者       互斥 消费者<----->消费者   场所:   缓冲区,下文以链表方式实现 1.单个生产者,单个消费者,且生产者和消费者访问链表的顺序是LIFO的 代码实现: #include<stdio.h> #include<pthread.h> pthread_mutex_t _mutex_lock=PTHREAD_

Linux同步与相互排斥应用(零):基础概念

[版权声明:尊重原创,转载请保留出处:blog.csdn.net/shallnet 或 .../gentleliu,文章仅供学习交流,请勿用于商业用途] 当操作系统进入多道批处理系统时代以后.一个系统中就存在多个任务,每一个任务都依照一定的算法进行调度来使用内存.cpu等共享资源. 当当中一个任务等待其它资源时,该任务能够临时睡眠,操作系统调度另外任务继续运行额,这样能够使系统资源得到最大化利用.而无需像曾经单道批处理系统那样仅仅有当一个任务完毕之后才运行下一个任务. 可是由此也引入了多任务并发

Linux 同步方法剖析--内核原子,自旋锁和相互排斥锁

在学习 Linux® 的过程中,您或许接触过并发(concurrency).临界段(critical section)和锁定,可是怎样在内核中使用这些概念呢?本文讨论了 2.6 版内核中可用的锁定机制,包含原子运算符(atomic operator).自旋锁(spinlock).读/写锁(reader/writer lock)和内核信号量(kernel semaphore). 本文还探讨了每种机制最适合应用到哪些地方.以构建安全高效的内核代码. 本文讨论了 Linux 内核中可用的大量同步或锁定