posix信号量 Link with -lpthread.

sem_t *sem_open(const char *name, int oflag);//打开POSIX信号量
sem_t *sem_open(const char *name, int oflag,mode_t mode, unsigned int value);

int sem_init(sem_t *sem, int pshared, unsigned int value);

posix互斥锁(第七章)
int pthread_mutex_destroy(pthread_mutex_t *mutex);
int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr);
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

有两个信号量。

p操作:测试信号量值大于0,减1.sem_wait
v操作:给定信号量值加1. sem_post
用posix信号量和互斥锁解决生产者消费者问题
一、生产者线程的任务:
p(sem_full),p一个满的信号量(缓冲区容量),如果仓库还没满(sem_full>0),我们就能生产产品。一旦我们
生产了一个产品,仓库既不是一个空的状态了,我们V一个空的信号量sem_empty.就告诉了消费者可以消费了。
由于可能有多个生产者,所以引入一个互斥量。
二:消费者的任务:
要p(sem_empty),如果生产者没有V一个sem_empty,消费者p操作sem_empty可能就不行,所以要等生产者生产了产品,
v了sem_empty通知到消费者,消费者才可以消费。一旦消费了一个产品,就可以V(sem_full)是的仓库容量减一(不满)通知
到生产者线程又可以生产了。由于可能有多个消费者,所以引入一个互斥量。

假设仓库容量为10,刚开始可以生产产品,所以sem_full(10)信号量初始值设为10,表示可以生产10个。
刚开始仓库中没有产品可以消费,所以sem_empty(0)初始值为0.

  1 #include<unistd.h>
2 #include<sys/types.h>
3 #include<fcntl.h>
4 #include<sys/stat.h>
5 #include<stdlib.h>
6 #include<stdio.h>
7 #include<errno.h>
8 #include <semaphore.h>
9 #include<pthread.h>
10 #define ERR_EXIT(m)\
11 do\
12 {\
13 perror(m);\
14 exit(EXIT_FAILURE);\
15 }while(0)
16 #define CONSUMERS_COUNT 1 //消费者线程个数
17 #define PRODUCERS_COUNT 2 //生产者线程个数
18 #define BUFFSIZE 10 //缓冲区大小(仓库大小)
19 int g_buffer[BUFFSIZE]; //环形缓冲区
20 unsigned short in=0; //初始生产产品放置位置
21 unsigned short out=0; //初始消费的产品位置
22 unsigned short produce_id=0;//当前正在消费的产品ID
23 unsigned short consume_id=0;//当前正在消费的产品ID
24 //两个信号量,一个互斥锁。
25 sem_t g_sem_full;//可生产产品的数量
26 sem_t g_sem_empty;//可消费产品的数量
27 pthread_mutex_t g_mutex;
28
29 pthread_t g_thread[CONSUMERS_COUNT+PRODUCERS_COUNT ];//线程ID.生产者线程个数+消费者线程个数
30 //消费者线程执行的任内务
31 void* consume(void*arg)
32 {
33 int num=(int)arg;
34 int i;
     //消费者不断消费
35 while(1)
36 {
37 printf("%d wait buffer not empty\n",num);
38 //sem_wait测试信号量值大于0减一并立即返回.P操作
39 sem_wait(&g_sem_empty);
40 pthread_mutex_lock(&g_mutex);
41 //消费之前打印基本信息
42 for(i=0;i<BUFFSIZE;i++)
43 {
44 printf("%02d ",i);//仓库序号
45 if(g_buffer[i]==-1)
46 printf("%s ","null");//仓库为空
47 else
48 printf("%d ",g_buffer[i]);
49 if(i==out)
50 printf("\t<--consume");//消费位置
51 printf("\n");
52 }
53 consume_id=g_buffer[out];
54 printf("%d begin consume product %d\n",num,consume_id);
55 g_buffer[out]=-1;
56 out=(out+1)%BUFFSIZE;
57 printf("%d end consume product %d\n",num,consume_id);
58 pthread_mutex_unlock(&g_mutex);
59 //给定信号量值加1。V操作,消费了一个产品,仓库就可以再生产产品
60 sem_post(&g_sem_full);
61 sleep(1);
62 }
63 return NULL;
64 }
65 //生产者线程执行的任务。
66 void* produce(void*arg)
67 {
68 int num=(int)arg;
69 int i;
70 while(1)
71 {
72 printf("%d wait buffer not full\n",num);
73 //sem_wait测试信号量值大于0减一并立即返回.g_sem_full代表可以生产的个数,生产了一个之后,可以生产的个数就要减一
74 //所以初始值为buffersize
75 sem_wait(&g_sem_full);
76 pthread_mutex_lock(&g_mutex);
77 //生产之前打印基本信息
78 for(i=0;i<BUFFSIZE;i++)
79 {
80 printf("%02d ",i);//仓库序号
81 if(g_buffer[i]==-1)
82 printf("%s ","null");//仓库为空
83 else
84 printf("%d ",g_buffer[i]);
85 if(i==in)
86 printf("\t<--produce");//生产位置
87 printf("\n");
88 }
89 printf("%d begin produce product %d\n",num,produce_id);
90 g_buffer[in]=produce_id;
91 in=(in+1)%BUFFSIZE;
92 printf("%d end produce product %d\n",num,produce_id++);
93 pthread_mutex_unlock(&g_mutex);
94 //生产了一个产品的话,就给g_sem_empty信号量值加1
95 sem_post(&g_sem_empty);
96 sleep(5);
97 }
98 return NULL;
99 }
100 int main(void)
101 {
102 int i;
103 for(i=0;i<BUFFSIZE;i++)
104 g_buffer[i]=-1;
105 //初始化信号量
106 sem_init(&g_sem_full,0,BUFFSIZE);
107 sem_init(&g_sem_empty,0,0);
108 //初始化互斥量
109 pthread_mutex_init(&g_mutex,NULL);
110
111 //创建若干个线程,执行消费任务。
112 for(i=0;i<CONSUMERS_COUNT;i++)
113 {
114 pthread_create(&g_thread[i],NULL,consume,(void*)i);//产生了段错误.我们传递的是值,所以int num=(int)arg 而不是int num=*(int*)arg
115 }
116 //创建若干个线程,执行生产任务。
117 for(i=0;i<PRODUCERS_COUNT;i++)
118 {
119 pthread_create(&g_thread[i+CONSUMERS_COUNT],NULL,produce,(void*)i);
120 }
121 //主线程等待这些线程结束
122 for(i=0;i<CONSUMERS_COUNT+PRODUCERS_COUNT;i++)
123 {
124 pthread_join(g_thread[i],NULL);
125 }
126
127 sem_destroy(&g_sem_full);//销毁POSIX信号量
128 sem_destroy(&g_sem_empty);
129 pthread_mutex_destroy(&g_mutex);
130 return 0;
131 }

POSIX信号量与互斥锁实现生产者消费者模型的更多相关文章

  1. posix 匿名信号量与互斥锁 示例生产者--消费者问题

    一.posix 信号量 信号量的概念参见这里.前面也讲过system v 信号量,现在来说说posix 信号量. system v 信号量只能用于进程间同步,而posix 信号量除了可以进程间同步,还 ...

  2. Linux多线程实践(5) --Posix信号量与互斥量解决生产者消费者问题

    Posix信号量 Posix 信号量 有名信号量 无名信号量 sem_open sem_init sem_close sem_destroy sem_unlink sem_wait sem_post ...

  3. linux网络编程之posix信号量与互斥锁

    继上次学习了posix线程之后,这次来讨论一下posix信号量与互斥锁相关的知识: 跟posix消息队列,共享内存的打开,关闭,删除操作一样,不过,上面的函数是对有名信号量进行操作,通过man帮助可以 ...

  4. python网络编程--进程(方法和通信),锁, 队列,生产者消费者模型

    1.进程 正在进行的一个过程或者说一个任务.负责执行任务的是cpu 进程(Process: 是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础.在 ...

  5. 线程高级篇-Lock锁实现生产者-消费者模型

    Lock锁介绍: 在java中可以使用 synchronized 来实现多线程下对象的同步访问,为了获得更加灵活使用场景.高效的性能,java还提供了Lock接口及其实现类ReentrantLock和 ...

  6. posix 条件变量与互斥锁 示例生产者--消费者问题

    一.posix 条件变量 一种线程间同步的情形:线程A需要等某个条件成立才能继续往下执行,现在这个条件不成立,线程A就阻塞等待,而线程B在执行过程中使这个条件成立了,就唤醒线程A继续执行. 在pthr ...

  7. 第三十九章 POSIX信号量与互斥锁

    POSIX信号量相关函数 sem_open 功能: initialize and open a named semaphore 原型: sem_t *sem_open(const char *name ...

  8. linux网络编程-posix信号量与互斥锁(39)

    -posix信号量信号量 是打开一个有名的信号量 sem_init是打开一个无名的信号量,无名信号量的销毁用sem_destroy sem_wait和sem_post是对信号量进行pv操作,既可以使用 ...

  9. posix信号量与互斥锁

    1.简介 POSIX信号量是一个sem_t 类型的变量,但POSIX 有两种信号量的实现机制:无名信号量和命名信号量.无名信号量可以用在共享内存的情况下, 比如实现进程中各个线程之间的互斥和同步.命名 ...

随机推荐

  1. 多测师讲解IDE工具python_001.2pycham_安装

    PyCharm安装使用教程 Pycharm 是目前 Python 语言最好用的集成开发工具. 下载 Pycharm 载时有两种版本选择 Professional(专业版,收费)和Community(社 ...

  2. 干货分享:用一百行代码做一个C/C++表白小程序,程序员的浪漫!

    前言:很多时候,当别人听到你是程序员的时候.第一印象就是,格子衫.不浪漫.直男.但是程序员一旦浪漫起来,真的没其他人什么事了.什么纪念日,生日,情人节,礼物怎么送? 做一个浪漫的程序给她,放上你们照片 ...

  3. spring cloud:搭建基于consul的服务提供者集群(spring cloud hoxton sr8 / spring boot 2.3.4)

    一,搭建基于consul的服务提供者集群 1,consul集群,共3个实例: 2, 服务提供者集群:共2个实例: 3,服务消费者:一个实例即可 4,consul集群的搭建,请参考: https://w ...

  4. Monolog - Logging for PHP

    github地址:https://github.com/Seldaek/monolog 使用 Monolog 安装 核心概念 日志级别 配置一个日志服务 为记录添加额外的数据 使用通道 自定义日志格式 ...

  5. swoole为什么不建议使用static和global

    $http = new swoole_http_server("0.0.0.0", 9501); $http->on("request", functio ...

  6. go 参数传递的是值还是引用 (转)

    https://blog.csdn.net/qq_16059847/article/details/104062759

  7. 电子阅读器.vbs

    CreateObject("SAPI.SpVoice").Speak"你要说的话!"

  8. spring-boot-route(二十)Spring Task实现简单定时任务

    Spring Task是Spring 3.0自带的定时任务,可以将它看作成一个轻量级的Quartz,功能虽然没有Quartz那样强大,但是使用起来非常简单,无需增加额外的依赖,可直接上手使用. 一 如 ...

  9. 不死的小强 .net core 微服务 快速开发框架 Viper 限流

    1.Viper是什么? Viper 是.NET平台下的Anno微服务框架的一个示例项目.入门简单.安全.稳定.高可用.全平台可监控.底层通讯可以随意切换thrift grpc. 自带服务发现.调用链追 ...

  10. spring-boot-route(二十三)开发微信公众号

    在讲微信公众号开发之前,先来大概了解一下微信公众号.微信公众号大体上可以分为服务号和订阅号,订阅号和服务号的区别如下: 服务号可以申请微信支付功能. 服务号只能由企业申请,订阅号可以有企业或个人申请. ...