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. 多测师讲解python _练习题003_高级讲师肖sir

    python 003作业题:# 1.分别打印100以内的所有偶数和奇数并存入不同的列表当中# 2.请写一段Python代码实现删除一个list = [1, 3, 6, 9, 1, 8]# 里面的重复元 ...

  2. 【故障公告】博客系统升级到 .NET 5.0 引发的故障

    昨天晚上我们将博客系统从 .NET Core 3.1 升级到了 .NET 5.0 ,本来是一次很有信心的升级,但没有想到在今天下午访问高峰时竟然出现了故障,大量请求访问速度变慢或者因为下面的数据库连接 ...

  3. Docker Stack 笔记

    Docker Compose (Docker Stack) image: Specify the image to start the container from. Can either be a ...

  4. BUUCTF-[极客大挑战 2019]HardSQL 1详解

    来到sql注入骚姿势,我们一点一点开始学 我们来到这道题,然后尝试注入,结果发现 拼接'or '1'='1 'or '1'='2如果是字符型注入则会报错,然而并没有而是显示的页面一样, 通过常规注入, ...

  5. Jmeter创建随机数作为参数使用 转

    1.选项-函数值手对话框:2.选择适当的函数,比如"__Random()":3.输入参数,比如随机数的最大.最小数:4."Name of variable in whic ...

  6. spring boot:使用poi导出excel电子表格文件(spring boot 2.3.1)

    一,什么是poi? 1,poi poi是用来兼容微软文档格式的java api, 它是apache的顶级项目之一, 也是我们在生产环境中导出excel时使用最多的库 2,poi官方网站: http:/ ...

  7. spring boot:发送带附件的邮件和html内容的邮件(以163.com邮箱为例/spring boot 2.3.2)

    一,网站哪些情况下需要发送电子邮件? 作为一个电商网站,以下情况需要发邮件通知用户: 注册成功的信息 用邮箱接收验证码 找回密码时发链接 发送推广邮件 下单成功后的订单通知 给商户的对账单邮件 说明: ...

  8. TimeSpan时间间隔详解

    1 public string GetShiXian(string fadanshijian) 2 { 3 string result,chulishijian; 4 5 DateTime fdTim ...

  9. HTML DOM Document的实际应用

    HTML文档中可以使用以下属性和方法: 属性 / 方法 描述 document.activeElement 返回当前获取焦点元素 document.addEventListener() 向文档添加句柄 ...

  10. mongodb 数据操作CRUD

    链接到mongo 新建超级用户 上文中我们提到mongo用户库表管理.为了方便我们先新建一个root权限的用户. db.createUser({user:'dbadmin',pwd:'123456', ...