信号量(semaphore)是一种用于提供不同进程之间或者一个给定的不同线程间同步手段的原语。信号量多用于进程间的同步与互斥,简单的说一下同步和互斥的意思:

同步:处理竞争就是同步,安排进程执行的先后顺序就是同步,每个进程都有一定的先后执行顺序。

互斥:互斥访问不可共享的临界资源,同时会引发两个新的控制问题(互斥可以说是特殊的同步)。

竞争:当并发进程竞争使用同一个资源的时候,我们就称为竞争进程。

共享资源通常分为两类:一类是互斥共享资源,即任一时刻只允许一个进程访问该资源;另一类是同步共享资源,即同一时刻允许多个进程访问该资源;信号量是解决互斥共享资源的同步问题而引入的机制。

1.概述:

简单说一下信号量的工作机制(因为真的很简单),可以直接理解成计数器(当然其实加锁的时候肯定不能这么简单,不只只是信号量了),信号量会有初值(>0),每当有进程申请使用信号量,通过一个P操作来对信号量进行-1操作,当计数器减到0的时候就说明没有资源了,其他进程要想访问就必须等待(具体怎么等还有说法,比如忙等待或者睡眠),当该进程执行完这段工作(我们称之为临界区)之后,就会执行V操作来对信号量进行+1操作。

临界区:临界区指的是一个访问共用资源(例如:共用设备或是共用存储器)的程序片段,而这些共用资源又无法同时被多个线程访问的特性。

临界资源:只能被一个进程同时使用(不可以多个进程共享),要用到互斥。

我们可以说信号量也是进程间通信的一种方式,比如互斥锁的简单实现就是信号量,一个进程使用互斥锁,并通知(通信)其他想要该互斥锁的进程,阻止他们的访问和使用。

当有进程要求使用共享资源时,需要执行以下操作:

1.系统首先要检测该资源的信号量;

2.若该资源的信号量值大于0,则进程可以使用该资源,此时,进程将该资源的信号量值减1;

3.若该资源的信号量值为0,则进程进入休眠状态,直到信号量值大于0时进程被唤醒,访问该资源;

当进程不再使用由一个信号量控制的共享资源时,该信号量值增加1,如果此时有进程处于休眠状态等待此信号量,则该进程会被唤醒。

2.信号量的具体结构

每个信号量集都有一个与其相对应的结构,该结构定义如下:

/* Data structure describing a set of semaphores.  */
struct semid_ds
{  struct ipc_perm sem_perm;   /* operation permission struct */  struct sem *sem_base;       /* ptr to array of semaphores in set */  unsigned short sem_nsems;   /* # of semaphores in set */  time_t sem_otime;           /* last-semop() time */  time_t sem_ctime;           /* last-change time */
};  /* Data structure describing each of semaphores.  */
struct sem
{  unsigned short semval;  /* semaphore value, always >= 0 */  pid_t          sempid;  /* pid for last successful semop(), SETVAL, SETALL */  unsigned short semncnt; /* # processes awaiting semval > curval */  unsigned short semzcnt; /* # processes awaiting semval == 0 */
};  

信号量集的结构图如下所示:

3.代码实现信号量

使用信号量实现生产者消费者模式

#include "stdafx.h"
#include <stdio.h>
#include <pthread.h>
#include <sched.h>
#include <semaphore.h>
#include <conio.h>
#include <ctype.h>
#include <signal.h>
#include <iostream>#include<Windows.h>
using namespace std;
#pragma comment(lib,"pthreadVC2.lib")  #define N 5  //消费者或者生产者的数目
#define M 10  //缓冲数目int productin = 0; //生产者放置产品的位置
int prochaseout = 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; //消费者idvoid SignalExit(int signo)
{printf("程序退出%d\n",signo);return;
}void PrintProduction()
{printf("此时的产品队列为::");for(int i = 0; i < M; i++ ){printf("%d  ",buff[i]);}printf("\n\n");
}//生产者方法
void* Product(void* pramter)
{int id = ++product_id;while(1){Sleep(5000); //毫秒sem_wait(&empty_sem); //给信号量减1操作pthread_mutex_lock(&mutex);productin = productin % M;printf("生产者%d在产品队列中放入第%d个产品\n\n",id,productin+1);buff[productin] = 1;PrintProduction();++productin;pthread_mutex_unlock(&mutex); //释放互斥量对象sem_post(&full_sem); //给信号量的值加1操作}
}//消费者方法///
void* Prochase( void* pramter )
{int id = ++prochase_id;while(1){Sleep(7000);sem_wait(&full_sem);pthread_mutex_lock(&mutex);prochaseout = prochaseout % M;printf("消费者%d从产品队列中取出第%d个产品\n\n",id,prochaseout+1);buff[prochaseout] = 0;PrintProduction();++prochaseout;pthread_mutex_unlock(&mutex);sem_post(&empty_sem);}
}int main()
{cout << "生产者和消费者数目都为5,产品缓冲区为10,生产者每2秒生产一个产品,消费者每5秒消费一个产品" << endl << endl;pthread_t productid[N];pthread_t prochaseid[N];int ret[N];//初始化信号量int seminit1 = sem_init(&empty_sem,0,M);int seminit2 = sem_init(&full_sem,0,0);if( seminit1 != 0  && seminit2 != 0 ){printf("sem_init failed !!!\n");return 0;}//初始化互斥信号量int mutexinit = pthread_mutex_init(&mutex,NULL);if( mutexinit != 0 ){printf("pthread_mutex_init failed !!\n");return 0;}//创建n个生产者线程for(int i = 0; i < N; i++ ){ret[i] = pthread_create( &productid[i], NULL,Product,(void*)(&i) );if( ret[i] != 0 ){printf("生产者%d线程创建失败!\n",i);return 0;}}//创建n个消费者线程for(int j = 0; j < N; j++ ){ret[j] = pthread_create(&prochaseid[j],NULL,Prochase,NULL);if( ret[j] != 0 ){printf("消费者%d线程创建失败\n",j);return 0;}}///等待线程被销毁///for( int k = 0; k < N; k++ ){printf("销毁线程\n");pthread_join(productid[k],NULL);pthread_join(prochaseid[k],NULL);}return 0;
}

进程间通信的方式(四):信号量相关推荐

  1. linux实现单机qq_Linux后台服务器开发——Linux下进程间通信的方式有哪些?

    Linux下进程间通信的方式有: 管道 消息队列 信号 信号量 共享存储 套接字 一.管道 管道是半双工的,数据只能向一个方向流动:需要双方通信时,需要建立起两个管道 PIPE无名管道 详情参阅:ht ...

  2. 进程间通信的方式——信号、管道、消息队列、共享内存

    进程间通信的方式--信号.管道.消息队列.共享内存 多进程: 首先,先来讲一下fork之后,发生了什么事情. 由fork创建的新进程被称为子进程(child process).该函数被调用一次,但返回 ...

  3. Linux多线程间通信和多进程间通信的方式

    文章目录 一.进程间的通信方式 1. 进程间通信的概念 1.1. 进程通信的目的: 1.2. Linux 进程间通信(IPC)的发展 2. 进程间通信的7种方式 2.1. 管道/匿名管道(pipe) ...

  4. linux进程间通信:system V 信号量 生产者和消费者模型编程案例

    生产者和消费者模型: 有若干个缓冲区,生产者不断向里填数据,消费者不断从中取数据 两者不冲突的前提: 缓冲区有若干个,且是固定大小,生产者和消费者各有若干个 生产者向缓冲区中填数据前需要判断缓冲区是否 ...

  5. 一种网络进程间通信的方式—— 管道

    一种网络进程间通信的方式-- 管道 摘要: 文章主要介绍了计算机网络进程间通信的必要性以及进程间通信所采用的几种方式,重点说明了管道通信的原理及命名管道的实现方法. 关键词:管道 命名管道 进程 一. ...

  6. C | 进程间通信的方式

    C | 进程间通信的方式 1.无名管道 无名管道是实现亲缘间进程通信的一种方式,属于半双工通信. 无名管道的实现是队列,不能使用lseek对读写指针偏移. 无名管道有两个端:数据流入端和数据流出端,也 ...

  7. 进程间通信的方式及原理

    # 进程间通信的方式 文章目录 # 进程间通信的方式 消息队列 使用步骤 管道 消息队列 信号 信号量 socket 消息队列 首先消息队列就是内核维护的一块链表区域,只要是有足够权限的进程都可以向队 ...

  8. 进程和线程的区别 及 进程间通信的方式

    1.进程和线程的区别 (1)进程和线程对比:         进程是对运行时程序的封装,是系统资源调度和分配的基本单位,进程可以看做是操作系统的并行机制.         线程是进程的子任务,cpu ...

  9. Linux进程间通信详解(四) —— 共享内存及函数

    共享内存的概念 共享内存是指多个进程可以把一段内存共同的内存映射到自己的进程空间中,从而实现数据的共享和传输,它是存在与内核级别的一种资源,是所有进程间通信中方式最快的一种. 在shell环境下可以使 ...

  10. mysql数据库启动_MySQL数据库之Mysql启动的方式(四种)

    本文主要向大家介绍了MySQL数据库之Mysql启动的方式(四种) ,通过具体的内容向大家展现,希望对大家学习MySQL数据库有所帮助. 废话不多说了,直奔主题了. mysql的四种启动方式: 1.m ...

最新文章

  1. Android支付接入(五):机锋网
  2. Java 8流:Micro Katas
  3. java反射 动态调用_java反射拼接方法名动态执行方法
  4. 遗传算法 差分进化算法 粒子群优化算法区别
  5. 设置或者获取CheckboxList控件的选中值
  6. 计算机网络超详细笔记(四):介质访问控制子层
  7. asymptotic (infinite-training-sample)
  8. 计算机网络和电气之间的联系,2020年电气工程师《基础知识》历年真题精选0830...
  9. 一种便携式导弹飞控系统外场实时仿真测试系统设计
  10. 学生个人网页模板 学生个人网页设计作品 简单个人主页成品 个人网页制作 HTML学生个人网站作业设计
  11. 《A Neural Layered Model for Nested Named Entity Recognition》
  12. Android多分辨率适配框架(1)— 核心基础
  13. JVAV-基础②标识符与运算符
  14. java二进制保存图片_Java中如何把图片转换成二进制流
  15. java代码到opcode_OPcode简介
  16. 手写笔迹还原算法(InkCanvas)
  17. COVID-19疫情数据可视化
  18. 医学图像处理开源软件集合
  19. U4 “U盘不能启动怎么办”-孙宇彤-专题视频课程
  20. 搭建一个Fabric网络

热门文章

  1. PAT-1124. Raffle for Weibo Followers (20)
  2. 【2016-09-27-DP小练】
  3. centos下添加的端口不能访问(防火墙关闭)
  4. mybatis 批量查询参数语句
  5. IDEA 部署项目的时候出错:Jar not loaded错误
  6. iPod/iTouch/ipad/iPhone新手注意事项
  7. memcached 的Linux安装
  8. flash mini播放器
  9. 谈题库系统(Samplx)项目之进展
  10. matlab 中的dir函数使用