文章目录

  • 一、信号量是什么?
  • 二、使用步骤
    • 1.用下面一组函数(系统调用)来实现对临界资源的访问
    • 2.信号量实现顺序操作
    • 3、信号量实现互斥操作

一、信号量是什么?

信号量(Semaphore),有时被称为信号灯,是在多线程环境下使用的一种设施,是可以用来保证两个或多个关键代码段不被并发调用,它的功能类似于互斥锁,但是它能提供更为高级的方法,以便进程能够同步活动。在进入一个关键代码段之前,线程必须获取一个信号量;一旦该关键代码段完成了,那么该线程必须释放信号量。其它想进入该关键代码段的线程必须等待直到第一个线程释放信号量。

二、使用步骤

1.用下面一组函数(系统调用)来实现对临界资源的访问

代码如下(示例):
int sem_init(sem_t *sem,int pshared,unsigned int value);
int sem_destroy(sem_t *sem);
int sem_wait(sem_t *sem);
int sem_trywait(sem_t *sem);
int sem_post(sem_t *sem);
int sem_getvalue(sem_t *sem);

看一个例子,比如有两个线程都要往打印机上打东西,但是同一时刻只能打一个。
那么首先用sem_init初始化一个信号量,注意pshared表示允许几个进程共享该信号量,一般设0用于进程内的多线程共享,要看是否支持进程共享,请查看下你的系统的man手册。
第三个参数value表示可用的资源的数目,即信号灯的数目,咱们这儿只有1个打印机所以设成1。
然后线程调用sem_wait取获取这个信号灯,第一个线程一看,有1个,他就拿到了,然后可以继续后继操作,此时信号灯自动减1,变成0个。那么第二个线程调用sem_wait时就会阻塞在这儿了。
第一个线程完成打印后,调用sem_post释放信号灯,信号灯数目变成1,将会唤醒等待的第二个线程,然后第二个线程接着打印。最后当所有任务完成后,主线程调用sem_destroy释放这个信号量。

sem_wait是一个函数,也是一个原子操作,它的作用是从信号量的值减去一个“1”,但它永远会先等待该信号量为一个非零值才开始做减法。也就是说,如果你对一个值为2的信号量调用sem_wait(),线程将会继续执行,将信号量的值将减到1。
如果对一个值为0的信号量调用sem_wait(),这个函数就会原地等待直到有其它线程增加了这个值使它不再是0为止。如果有两个线程都在sem_wait()中等待同一个信号量变成非零值,那么当它被第三个线程增加 一个“1”时,等待线程中只有一个能够对信号量做减法并继续执行,另一个还将处于等待状态。sem_trywait(sem_t *sem)是函数sem_wait的非阻塞版,它直接将信号量sem减1,同时返回错误代码。

2.信号量实现顺序操作

代码如下:

/*************************************************************************#   FileName   : pthreadsem.c#  Author     : fengjunhui #   Email      : 18883765905@163.com ************************************************************************/#include<stdio.h>
#include <pthread.h>
#include <semaphore.h>#define N 64
typedef struct message{char buf[N];int len;
}msg_t;sem_t sem_reverse;
sem_t sem_printf;void* reverse_msgbuf(void* arg)
{msg_t *msg = (msg_t *)arg;int i = 0;char tmp;while(1){sem_wait(&sem_reverse);    //sem_reverse有资源,先执行printf("reverse_msgbuf -------------\n");
#if 1for(i = 0; i < msg->len/2; i ++){tmp           = msg->buf[i];msg->buf[i]  = msg->buf[msg->len - i - 1];msg->buf[msg->len - i -1] = tmp;}
#endif sleep(1);printf("reverse_msgbuf :%s\n",msg->buf);sem_post(&sem_printf);//刚开始sem_printf没有资源,不能执行。//在这里逆置执行完成之后,给sem_printf资源,打印就可以执行了}
}void* printf_msgbuf(void* arg)
{msg_t *msg = (msg_t *)arg;while(1){sem_wait(&sem_printf); //sem_printf有资源,可以执行printf("printf_msgbuf :***********\n");printf("printf_msgbuf :%s\n",msg->buf);sem_post(&sem_reverse); //sem_printf执行完成之后,给sem_reverse资源,//那么sem_reverse就可以执行了}
}int main(int argc, const char *argv[])
{msg_t msg = {"123456789",9};pthread_t tid[2];sem_init(&sem_reverse,0,1);//sem_reverse有一个资源sem_init(&sem_reverse,0,0);//sem_reverse没有资源pthread_create(&tid[0],NULL,reverse_msgbuf,(void *)&msg);pthread_create(&tid[1],NULL,printf_msgbuf,(void *)&msg);pause();return 0;
}

3、信号量实现互斥操作

while(1){sem_wait(&sem_printf);//消耗一个资源printf("printf_msgbuf :***********\n");printf("printf_msgbuf :%s\n",msg->buf);sem_post(&sem_printf);//得到一个资源}

信号量sem_wait()函数的学习相关推荐

  1. 线程:信号量 sem_wait sem_post

    信号量的数据类型为结构sem_t,它本质上是一个长整型的数.函数sem_init()用来初始化一个信号量.它的原型为: extern int sem_init __P ((sem_t *__sem, ...

  2. linux中sem_wait函数,semwait sem_wait的函数说明

    sem_wait() 减小(锁定)由sem指定的信号量的值.如果信号量的值比0大,那么进行减一的操作,函数立即返回.如果信号量当前为0值,那么调用就会一直阻塞直到或者是信号量变得可以进行减一的操作(例 ...

  3. SQL 2005新增的几个函数之学习

    sqlserver 2005新增函数学习(转载) 原文:SQL 2005新增的几个函数之学习 今天学习了sql server 2005新增的几个函数,分别是row_number(),rank,DENS ...

  4. ES6基础(var let const 箭头函数)-学习笔记

    文章目录 ES6基础(var let const 箭头函数)- 学习笔记 定义:var let const 箭头函数 数据结构 set map ES6基础(var let const 箭头函数)- 学 ...

  5. 信号量 Linux函数 semget();semctl();semop();

    Linux进程通信之信号量 信号量(semaphore)是变量,是一种特殊的变量.它紧取正值.对信息号量的操作只有2中: 等待(wait)和发送信号(signal). 信号量比较难理解.下面我们一个个 ...

  6. Matlab函数功能学习记录(1)

    初学乍练之作 优秀的Matlab讲解: 博客园 Matlab - 基础知识 csdn matlab库函数大全 my Matlab函数功能学习记录(2) Matlab特殊字符.命令和函数 Matlab实 ...

  7. print函数的学习与总结

    print函数的学习与总结 1 1. 单引号与双引号的区别 1.相同作用是当打印文字与字母及特殊符号时,使用单引号或双引号打印都可以. (1)单引号 print('哪吒') $python main. ...

  8. R语言与函数估计学习笔记(函数模型的参数估计)

    R语言与函数估计学习笔记 毫无疑问,函数估计是一个比参数估计要复杂得多的问题,当然也是一个有趣的多的问题.这个问题在模型未知的实验设计的建模中十分的常见,也是我正在学习的内容的一部分. 关于函数估计我 ...

  9. Linux中多线程使用信号量(信号灯),和sem_wait()函数使用

    文章目录 编程环境: 信号量(信号灯): 使用步骤: "生产者-消费者"例子: 理论模型: 代码分析: 代码实现: 运行结果: Mac 下对 sem_init()/sem_dest ...

最新文章

  1. python paramiko模块 远程上传目录文件
  2. lnmp 切换mysql 版本_LNMP1.5:php多版本切换
  3. [云炬创业基础笔记]第五章创业机会评估测试10
  4. 带注释的c51汇编语言,51单片机汇编语言实现交通灯 代码有详细注释
  5. java通过匹配合并数据(数据预处理)
  6. CentOs基础操作指令(进程管理)
  7. IE 下 telerik RadAjaxManager 多次请求,LoadingPanel 点击消失
  8. 公式推导 11-21
  9. easy2game使用教程_Easy2game什么用
  10. vbs如何调用c语言函数,VBS编程教程 (第6篇)
  11. 大一acmer日常记录day15
  12. 支付宝小程序使用 icontfont字体图标
  13. Java SE 007 循环控制语句
  14. Nginx 配置域名
  15. 我与学霸的距离计算机,你与学霸的距离,可能就差本笔记
  16. git clone 项目时总是提示输入密码
  17. 25个技巧和诀窍可以用来提高你的app性能
  18. 基于机器学习的敏感信息泄露治理探索
  19. 数学小游戏:原创字谜几则
  20. 【编程不良人】快速入门Spring学习笔记08---事务属性、Spring整合Structs2框架(SM)、Spring整合Mybatis+Struts2(SSM)、Spring注解、SSM注解式开发

热门文章

  1. 算法精解----log符号什么意思
  2. P2002 消息扩散(图论 Tarjan缩点)
  3. Gradle 实现 Android 多渠道定制化打包
  4. 微信小程序的推广方案有哪些
  5. OSPF网络类型以及不规则区域练习
  6. JavaScript实战练习——图片裁剪
  7. 【软件工程系列】结构化需求分析
  8. 源码编译更新nginx到最新版本,并开始nginx支持http2协议模块.
  9. 1.《阿西莫夫:机器人短篇全集》
  10. 深度学习、机器学习毕业设计 - 选题建议