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


是打开一个有名的信号量
sem_init是打开一个无名的信号量,无名信号量的销毁用sem_destroy
sem_wait和sem_post是对信号量进行pv操作,既可以使用在有名的信号量也可以使用在无名的信号量
无名信号量是否意味着它不能够用于不同进程的多个线程之间的通信了

如果sem_init是非零的参数,那么这个无名的信号量可以用于不同进程间的多个线程之间的通信,前提条件是这个信号量的对象必须存储在共享内存区才可以。

上面这是互斥锁是无名的互斥锁,同样也可以可以用于不同进程间的多个线程之间的通信,前提条件是这个信号量的对象必须存储在共享内存区才可以。
下面我们使用互斥锁来解决生产者消费者的问题
生产者消费者问题是这样描述的,有一个缓冲区,是一个有大小的缓冲区,对于生产者来说,首先判断当前缓冲区是否满了,满了就阻塞不再生产,我们使用信号量来实现
使用信号量p(sem_full)的信号量来实现,初始化的值就是缓冲区的大小,一旦生产了一个产品sem_full的计数值值减一,一旦我们生成了产品,缓冲区不再是空的状态,我们使用一个
v(sem_empty)的信号量,用来告诉消费者可以来消费产品了,我们在生成产品的时候,由于生产者可能是多个,我们需要有一个互斥锁来包含缓冲区。

对于消费者,消费者也存在多个,首先判断当前缓冲区是否是空的,如果是空的就不能消费产品,需要等待生产者给消费者一个信号,消费者新建一个p(sem_empty)信号,使得信号量加一,这样消费者就可以消费产品了,
一旦消费者消费了一个产品,就会使得缓冲区的大小加一v(sem_full)这样的信号量,对于缓冲区,多个消费者也需要互斥

对于初始化,一开始只能生产产品,不能消费产品,假设缓冲区的大小是10,sem_full是10,sem_empty为0

下面我们通过代码来理解下面的问题:
信号量是在多线程环境中共享资源的计数器
sem_wait() 减小(锁定)由sem指定的信号量的值.如果信号量的值比0大,
那么进行减一的操作,函数立即返回.
如果信号量当前为0值,那么调用就会一直阻塞直到或者是信号量变得可以进行减一的操作
(例如,信号量的值比0大),或者是信号处理程序中断调用
当前初始化的sem_full的值是10,减一之后函数会立即返回不会阻塞
sem_wait sem_post
extern int sem_init __P ((sem_t *__sem, int __pshared, unsigned int __value));
sem为指向信号量结构的一个指针;pshared不为0时此信号量在进程间共享,否则只能为当前进程的所有线程共享;value给出了信号量的初始值。
函数sem_post( sem_t *sem )用来增加信号量的值。当有线程阻塞在这个信号量上时,调用这个函数会使其中的一个线程不在阻塞,选择机制同样是由线程的调度策略决定的。
函数sem_wait( sem_t *sem )被用来阻塞当前线程直到信号量sem的值大于0,解除阻塞后将sem的值减一,表明公共资源经使用后减少。函数sem_trywait ( sem_t *sem )是函数sem_wait()的非阻塞版本,它直接将信号量sem的值减一。
函数sem_destroy(sem_t *sem)用来释放信号量sem。
信号量用sem_init函数创建的,下面是它的说明:
#include<semaphore.h>
int sem_init (sem_t *sem, int pshared, unsigned int value);
生产完一个产品之后sem_post(&sem_empty)是的sem_empty的信号量的值加一
我们来看程序的代码:
#include <unistd.h>
#include <sys/types.h>
#include <pthread.h>
#include <semaphore.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#define ERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
} while(0)
#define CONSUMERS_COUNT 1
#define PRODUCERS_COUNT 1
#define BUFFSIZE 10
int g_buffer[BUFFSIZE];
unsigned short in = 0;
unsigned short out = 0;
unsigned short produce_id = 0;
unsigned short consume_id = 0;
sem_t g_sem_full;
sem_t g_sem_empty;
pthread_mutex_t g_mutex;
pthread_t g_thread[CONSUMERS_COUNT + PRODUCERS_COUNT];
void *consume(void *arg)
{
int i;
int num = (int)arg;
while (1)
{
printf("%d wait buffer not empty\n", num);
sem_wait(&g_sem_empty);
pthread_mutex_lock(&g_mutex);
for (i = 0; i < BUFFSIZE; i++)
{
printf("%02d ", i);
if (g_buffer[i] == -1)
printf("%s", "null");
else
printf("%d", g_buffer[i]);
if (i == out)
printf("\t<--consume");
printf("\n");
}
consume_id = g_buffer[out];
printf("%d begin consume product %d\n", num, consume_id);
g_buffer[out] = -1;
out = (out + 1) % BUFFSIZE;
printf("%d end consume product %d\n", num, consume_id);
pthread_mutex_unlock(&g_mutex);
sem_post(&g_sem_full);
sleep(1);
}
return NULL;
}
void *produce(void *arg)
{
int num = (int)arg;
int i;
while (1)
{
printf("%d wait buffer not full\n", num);
sem_wait(&g_sem_full);
pthread_mutex_lock(&g_mutex);
for (i = 0; i < BUFFSIZE; i++)
{
printf("%02d ", i);
if (g_buffer[i] == -1)
printf("%s", "null");
else
printf("%d", g_buffer[i]);
if (i == in)
printf("\t<--produce");
printf("\n");
}
printf("%d begin produce product %d\n", num, produce_id);
g_buffer[in] = produce_id;
in = (in + 1) % BUFFSIZE;
printf("%d end produce product %d\n", num, produce_id++);
pthread_mutex_unlock(&g_mutex);
sem_post(&g_sem_empty);
sleep(5);
}
return NULL;
}
int main(void)
{
int i;
for (i = 0; i < BUFFSIZE; i++)
g_buffer[i] = -1;
sem_init(&g_sem_full, 0, BUFFSIZE);
sem_init(&g_sem_empty, 0, 0);
pthread_mutex_init(&g_mutex, NULL); for (i = 0; i < CONSUMERS_COUNT; i++)
pthread_create(&g_thread[i], NULL, consume, (void *)i);
for (i = 0; i < PRODUCERS_COUNT; i++)
pthread_create(&g_thread[CONSUMERS_COUNT + i], NULL, produce, (void *)i);
for (i = 0; i < CONSUMERS_COUNT + PRODUCERS_COUNT; i++)
pthread_join(g_thread[i], NULL);
sem_destroy(&g_sem_full);
sem_destroy(&g_sem_empty);
pthread_mutex_destroy(&g_mutex);
return 0;
}
编译的时候需要加上gcc proudct.c -o product -lpthread
可以查看博客:
http://blog.csdn.net/nk_test/article/details/50449704
linux网络编程-posix信号量与互斥锁(39)的更多相关文章
- linux网络编程之posix信号量与互斥锁
继上次学习了posix线程之后,这次来讨论一下posix信号量与互斥锁相关的知识: 跟posix消息队列,共享内存的打开,关闭,删除操作一样,不过,上面的函数是对有名信号量进行操作,通过man帮助可以 ...
- POSIX信号量与互斥锁实现生产者消费者模型
posix信号量 Link with -lpthread. sem_t *sem_open(const char *name, int oflag);//打开POSIX信号量 sem_t *sem_o ...
- Linux——临界段,信号量,互斥锁,自旋锁,原子操作
一. linux为什么需要临界段,信号量,互斥锁,自旋锁,原子操作? 1.1. linux内核后期版本是支持多核CPU以及抢占式调度.这里就存在一个并发,竞争状态(简称竟态). 1.2. 竞态条件 发 ...
- 第三十九章 POSIX信号量与互斥锁
POSIX信号量相关函数 sem_open 功能: initialize and open a named semaphore 原型: sem_t *sem_open(const char *name ...
- posix信号量与互斥锁
1.简介 POSIX信号量是一个sem_t 类型的变量,但POSIX 有两种信号量的实现机制:无名信号量和命名信号量.无名信号量可以用在共享内存的情况下, 比如实现进程中各个线程之间的互斥和同步.命名 ...
- linux网络编程-posix条件变量(40)
举一个列子来说明条件变量: 假设有两个线程同时访问全局变量n,初始化值是0, 一个线程进入临界区,进行互斥操作,线程当n大于0的时候才执行下面的操作,如果n不大于0,该线程就一直等待. 另外一个线程也 ...
- posix 匿名信号量与互斥锁 示例生产者--消费者问题
一.posix 信号量 信号量的概念参见这里.前面也讲过system v 信号量,现在来说说posix 信号量. system v 信号量只能用于进程间同步,而posix 信号量除了可以进程间同步,还 ...
- 漫画|Linux 并发、竞态、互斥锁、自旋锁、信号量都是什么鬼?(转)
知乎链接:https://zhuanlan.zhihu.com/p/57354304 1. 锁的由来? 学习linux的时候,肯定会遇到各种和锁相关的知识,有时候自己学好了一点,感觉半桶水的自己已经可 ...
- linux网络编程基础--(转自网络)
转自 http://www.cnblogs.com/MyLove-Summer/p/5215287.html Linux下的网络编程指的是socket套接字编程,入门比较简单. 1. socket套接 ...
随机推荐
- Java IO(九)FilterInputStream 和 FilterOutputStream
Java IO(九)FilterInputStream 和 FilterOutputStream 一.介绍 FilterInputStream 和 FilterOutputStream 是过滤字节输入 ...
- Chisel3 - Tutorial - FullAdder
https://mp.weixin.qq.com/s/Aye-SrUUuIP6_o67Rlt5OQ 全加器 逻辑图如下: 参考链接: https://github.com/ucb-b ...
- java实现 洛谷 P1540 机器
import java.util.LinkedList; import java.util.Scanner; public class Main { private static Scanner ci ...
- Linux 用户管理命令-usermod和chage
usermod和useradd命令的使用相类似,useradd针对的是新创建的用户可以修改他的信息,usermod则可以修改已经存在的用户的信息,选项也基本相同 usermod [选项] 用户名 -L ...
- portapack发射GPS的信号实现GPS脱机模拟器
要注意portapack必须要购买带高精度晶振的版本,另外固件要刷gridRF版本,用官方的或者havoc的都不行. 固件在这下载: 链接: https://pan.baidu.com/s/16flB ...
- Shell中傻傻分不清楚的TOP3
Shell中傻傻分不清楚的TOP3 发布文章 近来小姐姐又犯憨憨错误,问组内小伙伴export命令不会持久化环境变量吗?反正我是问出口了..然后小伙伴就甩给了我一个<The Linux Comm ...
- java正则匹配 指定内容以外的 内容
今天,遇到一个需要 匹配出 指定内容以外的 内容的需求. 乍一看,需求貌视很简单啊,直接上 非贪婪模式的 双向零宽断言(有的资料上也叫 预搜索.预查.环视lookaround): 比如,我要匹配 串内 ...
- java关键字static用法详解
java中有53个关键字,其中包含2个保留字,这篇文章主要介绍一下static这个关键字. static在java中算是一个比较常见的关键字,有着多种用法,因此很有必要好好地了解一番. 一.定义 st ...
- 在WinForms里嵌入MediaPlayer的一些版本问题, tlbimp导入, 以及不导入而纯用C#+字符串来动态调用.
网上很多写使用WindowsMediaPlayer WMP控件的文章. 大多数都是从工具栏或COM导入. 最近正在做的CEF整合Asp.Net Core Blazor server side的过程中, ...
- 查询局域网指定段内存活IP
目录 批量ping 输出到指定文件 批量ping for /L %i IN (起始,扫描间距,结束) DO ping -w 2 -n 1 10.224.131.%i 如 for /L %i IN (5 ...