进程同步问题-生产者消费者问题(linux semaphore实现)

本文地址:
http://blog.csdn.net/qq_26437925/article/details/52638582

源代码地址(通过ubuntu14.04 32bit 测试):
https://github.com/doctording/clib/tree/master/thread/producer_consumer


学习目标:

  • linux 线程
  • linux 信号(Semaphore)的使用
  • makefile书写
  • 生产者,消费者问题理解

原文参考
csdn博客专家:MoreWindows
秒杀多线程第十篇 生产者消费者问题
http://blog.csdn.net/lisonglisonglisong/article/details/45390227

linux ftok()函数
http://www.cnblogs.com/joeblackzqq/archive/2011/05/31/2065161.html

图书参考
《unix环境高级编程》/ APUE


在源代码基础上写改了下,是能够在本机上运行,并且编写了makefile文件。
semaphore 的semget,semctl,semop这几个函数要重点观察


生产者消费者问题进程描述

semaphore mutex=1; //临界区互斥信号量
semaphore empty=n;  //空闲缓冲区
semaphore full=0;  //缓冲区初始化为空
producer () { //生产者进程
    while(1){
        produce an item in nextp;  //生产数据
        P(empty);  //获取空缓冲区单元
        P(mutex);  //进入临界区.
        add nextp to buffer;  //将数据放入缓冲区
        V(mutex);  //离开临界区,释放互斥信号量
        V(full);  //满缓冲区数加1
    }
}

consumer () {  //消费者进程
    while(1){
        P(full);  //获取满缓冲区单元
        P(mutex);  // 进入临界区
        remove an item from buffer;  //从缓冲区中取出数据
        V (mutex);  //离开临界区,释放互斥信号量
        V (empty) ;  //空缓冲区数加1
        consume the item;  //消费数据
    }
}

注意:生产者先 p(mutex) , 再 p(empty), 消费者先p(metux) 再p(full) 不可行

当生产者进程已经放满缓冲区时,消费者没有取产品即empty=0, 当下次仍然是生产者进程运行时
他先执行p(mutex)封锁信号量,在执行p(empty)时被阻塞,希望消费者取出产品后 将其唤醒。
轮到消费者进程运行时,先p(metux) 而生产者已经封锁了mutex信号量,这是消费者将被阻塞。
这样双方都陷入了无休止的等待。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以帮你回答这个问题。 生产者-消费者问题是一个经典的进程同步问题,它的场景是这样的:有一些生产者进程和一些消费者进程,它们共享一个有限的缓冲区。生产者进程会往缓冲区中放入数据,而消费者进程则从缓冲区中取出数据。由于缓冲区是有限的,所以需要保证生产者和消费者之间的同步,以避免出现数据竞争和死锁等问题。 在Linux中,可以使用信号量机制来解决这个问题。下面是一个使用信号量机制实现生产者-消费者问题的C程序: ```c #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <pthread.h> #include <semaphore.h> #define BUFFER_SIZE 10 // 缓冲区大小 #define PRODUCER_NUM 5 // 生产者数量 #define CONSUMER_NUM 5 // 消费者数量 #define ITEM_COUNT 20 // 生产者和消费者共同生产的产品数量 int buffer[BUFFER_SIZE]; // 缓冲区 int in = 0; // 缓冲区中下一个可写入位置的索引 int out = 0; // 缓冲区中下一个可读取位置的索引 sem_t buffer_mutex; // 缓冲区的互斥信号量 sem_t empty_count; // 缓冲区中空位的数量 sem_t full_count; // 缓冲区中已经有数据的数量 void *producer(void *arg); // 生产者线程函数 void *consumer(void *arg); // 消费者线程函数 int main(int argc, char **argv) { // 初始化信号量 sem_init(&buffer_mutex, 0, 1); sem_init(&empty_count, 0, BUFFER_SIZE); sem_init(&full_count, 0, 0); // 创建生产者线程 pthread_t producer_threads[PRODUCER_NUM]; for (int i = 0; i < PRODUCER_NUM; i++) { pthread_create(&producer_threads[i], NULL, producer, (void *)(long)i); } // 创建消费者线程 pthread_t consumer_threads[CONSUMER_NUM]; for (int i = 0; i < CONSUMER_NUM; i++) { pthread_create(&consumer_threads[i], NULL, consumer, (void *)(long)i); } // 等待所有线程结束 for (int i = 0; i < PRODUCER_NUM; i++) { pthread_join(producer_threads[i], NULL); } for (int i = 0; i < CONSUMER_NUM; i++) { pthread_join(consumer_threads[i], NULL); } // 销毁信号量 sem_destroy(&buffer_mutex); sem_destroy(&empty_count); sem_destroy(&full_count); return 0; } void *producer(void *arg) { int id = (int)(long)arg; for (int i = 0; i < ITEM_COUNT; i++) { // 生产一个产品 int item = rand() % 100; // 等待缓冲区中有空位 sem_wait(&empty_count); // 获取缓冲区的互斥锁 sem_wait(&buffer_mutex); // 将产品放入缓冲区中 buffer[in] = item; in = (in + 1) % BUFFER_SIZE; printf("producer %d produces item %d\n", id, item); // 释放缓冲区的互斥锁 sem_post(&buffer_mutex); // 增加缓冲区中已有数据的数量 sem_post(&full_count); } return NULL; } void *consumer(void *arg) { int id = (int)(long)arg; for (int i = 0; i < ITEM_COUNT; i++) { // 等待缓冲区中有数据 sem_wait(&full_count); // 获取缓冲区的互斥锁 sem_wait(&buffer_mutex); // 从缓冲区中取出一个产品 int item = buffer[out]; out = (out + 1) % BUFFER_SIZE; printf("consumer %d consumes item %d\n", id, item); // 释放缓冲区的互斥锁 sem_post(&buffer_mutex); // 增加缓冲区中空位的数量 sem_post(&empty_count); } return NULL; } ``` 在这个程序中,我们使用了三个信号量来保证生产者和消费者之间的同步: - `buffer_mutex`是缓冲区的互斥信号量,用来保证同时只有一个线程可以操作缓冲区。 - `empty_count`是缓冲区中空位的数量信号量,用来表示缓冲区中还有多少个空位可以放置数据。 - `full_count`是缓冲区中已经有数据的数量信号量,用来表示缓冲区中已经有多少个数据可以被消费。 在生产者线程中,我们首随机生成一个产品,然后等待缓冲区中有空位。如果缓冲区中有空位,我们就获取缓冲区的互斥锁,将产品放入缓冲区中,并增加缓冲区中已有数据的数量。最后,释放缓冲区的互斥锁和增加缓冲区中空位的数量。 在消费者线程中,我们首等待缓冲区中有数据。如果缓冲区中有数据,我们就获取缓冲区的互斥锁,从缓冲区中取出一个产品,并增加缓冲区中空位的数量。最后,释放缓冲区的互斥锁和增加缓冲区中已有数据的数量。 通过使用信号量机制,我们可以保证生产者和消费者之间的同步,避免了数据竞争和死锁问题

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值