Linux信号量机制(生产者消费者)
2015-12-15 17:23
567 查看
该程序为Linux信号量机制实现程序,主要模拟了一般的生产者-消费者问题。(生产者-消费者问题是一个经典的进程同步问题,该问题最早由Dijkstra提出,用以演示他提出的信号量机制。在同一个进程地址空间内执行的两个线程。生产者线程生产物品,然后将物品放置在一个空缓冲区中供消费者线程消费。消费者线程从缓冲区中获得物品,然后释放缓冲区。当生产者线程生产物品时,如果没有空缓冲区可用,那么生产者线程必须等待消费者线程释放出一个空缓冲区。当消费者线程消费物品时,如果没有已用的缓冲区,那么消费者线程将被阻塞,直到新的物品被生产出来。
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <pthread.h> #include <semaphore.h> #include <signal.h> #define N 5 // 消费者或者生产者的数目 #define M 10 // 缓冲数目 //int M=10; int in = 0; // 生产者放置产品的位置 int out = 0; // 消费者取产品的位置 int buff[M] = { 0 }; // 缓冲初始化为0,开始时没有产品 sem_t empty_sem; // 同步信号量,当满了时阻止生产者放产品 sem_t full_sem; // 同步信号量,当没产品时阻止消费者消费 pthread_mutex_t mutex; // 互斥信号量,一次只有一个线程访问缓冲 int product_id = 0; //生产者id int prochase_id = 0; //消费者id //信号处理函数 void Handlesignal(int signo){ printf("程序退出\n",signo); exit(0); } /* 打印缓冲情况 */ void print() { int i; printf("产品队列为"); for(i = 0; i < M; i++) printf("%d", buff[i]); printf("\n"); } /* 生产者方法 */ void *product() { int id = ++product_id; while(1) {//重复进行 //用sleep的数量可以调节生产和消费的速度,便于观察 sleep(2); sem_wait(&empty_sem); pthread_mutex_lock(&mutex); in= in % M; printf("生产者%d在产品队列中放入第%d个产品\t",id, in); buff[in]= 1; print(); ++in; pthread_mutex_unlock(&mutex); sem_post(&full_sem); } } /* 消费者方法 */ void *prochase() { int id = ++prochase_id; while(1) {//重复进行 //用sleep的数量可以调节生产和消费的速度,便于观察 sleep(5); sem_wait(&full_sem); pthread_mutex_lock(&mutex); out= out % M; printf("消费者%d从产品队列中取出第%d个产品\t",id, out); buff[out]= 0; print(); ++out; pthread_mutex_unlock(&mutex); sem_post(&empty_sem); } } int main() { printf("生产者和消费者数目都为5,产品缓冲为10,生产者每2秒生产一个产品,消费者每5秒消费一个产品,Ctrl+退出程序\n"); pthread_t id1 ; pthread_t id2 ; int i; int ret ; //结束程序 if(signal(SIGINT,Handlesignal)==SIG_ERR){//按ctrl+C产生SIGINT信号 printf("信号安装出错\n"); } // 初始化同步信号量 int ini1 = sem_init(&empty_sem, 0, M);//产品队列缓冲同步 int ini2 = sem_init(&full_sem, 0, 0);//线程运行同步 if(ini1 && ini2 != 0) { printf("信号量初始化失败!\n"); exit(1); } //初始化互斥信号量 int ini3 = pthread_mutex_init(&mutex, NULL); if(ini3 != 0) { printf("线程同步初始化失败!\n"); exit(1); } // 创建N个生产者线程 for(i = 0; i < N; i++) { ret[i]= pthread_create(&id1[i], NULL, product, (void *) (&i)); if(ret[i] != 0) { printf("生产者%d线程创建失败!\n", i); exit(1); } } //创建N个消费者线程 for(i = 0; i < N; i++) { ret[i]= pthread_create(&id2[i], NULL, prochase, NULL); if(ret[i] != 0) { printf("消费者%d线程创建失败!\n", i); exit(1); } } //等待线程销毁 for(i = 0; i < N; i++) { pthread_join(id1[i], NULL); pthread_join(id2[i],NULL); } exit(0); }
在linux下编译语句为:gcc -o producer_consumer.out producer_consumer.c -lpthread
这个是因为pthread并非Linux系统的默认库,编译时注意加上-lpthread参数,以调用链接库相关文章推荐
- Linux socket 初步
- linux lsof详解
- linux 文件权限
- Linux 执行数学运算
- 10 篇对初学者和专家都有用的 Linux 命令教程
- Linux 与 Windows 对UNICODE 的处理方式
- Ubuntu12.04下QQ完美走起啊!走起啊!有木有啊!
- 解決Linux下Android开发真机调试设备不被识别问题
- 运维入门
- 运维提升
- Linux 自检和 SystemTap
- Ubuntu Linux使用体验
- c语言实现hashmap(转载)
- Linux 信号signal处理机制
- linux下mysql添加用户
- Scientific Linux 5.5 图形安装教程
- 基于 Linux 集群环境上 GPFS 的问题诊断
- 谁是桌面王者?Win PK Linux三大镇山之宝
- vivi下重新调整分区