linux多线程编程5--信号量(semaphore)

信号量本质上是一个非负的整数计数器,也是UNIX中古老的实现进程互斥和同步的手段,Linux下信号量概念是在线程中,信号则在进程控制中,不过原理差不多,最基本最经典的操作莫过于P、V操作了,能实现进程、线程的互斥和同步操作,非常值得深入理解。

1.P、V操作原语

 P操作:

 proceduce P(var s:semaphore)

{

  begin

      s:=s-1;

      if(s<0)then W(s);

  end

}

V操作:

 proceduce V(var s:semaphore)

{

  begin

      s:=s+1;

      if(s<=0)then R(s);

  end

}

2.基本操作

数据类型:信号量的数据类型为结构sem_t,它本质上是一个长整型的数。

函数:

(1)sem_init

功能:         用于创建一个信号量,并初始化信号量的值。

头文件:       <semaphore.h>

函数原型:     int sem_init (sem_t* sem, int pshared, unsigned int value);

函数传入值:   sem:信号量。

                   pshared:决定信号量能否在几个进程间共享。由于目前LINUX还没有实现进

                               程间共享信息量,所以这个值只能取0。

                   value:初始计算器

函数返回值:   0:成功。

                   -1:失败。

(2)其他函数。

//等待信号量

int sem_wait       (sem_t* sem);

int sem_trywait   (sem_t* sem);

//发送信号量

int sem_post       (sem_t* sem);

//得到信号量值

int sem_getvalue (sem_t* sem);

//删除信号量

int sem_destroy   (sem_t* sem);

功能:sem_wait和sem_trywait相当于P操作,它们都能将信号量的值减一,两者的区别在

        于若信号量的值小于零时,sem_wait将会阻塞进程,而sem_trywait则会立即返回。

        sem_post相当于V操作,它将信号量的值加一,同时发出唤醒的信号给等待的进程

       (或线程)。

        sem_getvalue 得到信号量的值。

        sem_destroy 摧毁信号量。

函数传入值: sem:信号量。

函数返回值: 同上。

好了,了解完基本操作,继续做一个练习:

这里用信号量实现互斥资源访问的功能:

 

/*sem.c*/ 
#include <stdlib.h>    
#include <stdio.h>    
#include <pthread.h>    
#include <semaphore.h>  
#include <errno.h>     
 
/*全局变量*/ 
int gnum = 0;  
/*信号量*/ 
sem_t sem;  
/*声明线程运行服务程序*/ 
static void pthread_func_1 (void);     
static void pthread_func_2 (void);     
    
int main (void)     
{     
 /*线程的标识符*/ 
  pthread_t pt_1 = 0;     
  pthread_t pt_2 = 0;     
  int ret = 0;     
 
  /*信号量初始化*/ 
  sem_init(&sem,0,1);  
  /*分别创建线程1、2*/ 
  ret = pthread_create (&pt_1,          //线程标识符指针  
                         NULL,          //默认属性  
                        (void *)pthread_func_1,//运行函数  
                        NULL);          //无参数  
  if (ret != 0)     
  {     
     perror ("pthread_1_create");     
  }     
    
  ret = pthread_create (&pt_2,          //线程标识符指针  
                        NULL,           //默认属性    
                        (void *)pthread_func_2, //运行函数  
                        NULL);          //无参数  
  if (ret != 0)     
  {     
     perror ("pthread_2_create");     
  }     
  /*等待线程1、2的结束*/ 
  pthread_join (pt_1, NULL);     
  pthread_join (pt_2, NULL);     
    
  printf ("main programme exit!/n");    
  return 0;     
}     
 
/*线程1的服务程序*/ 
static void pthread_func_1 (void)     
{     
  int i = 0;     
       
  for (;;)     
  {     
    printf ("This is pthread1!/n");      
    sem_wait(&sem);     /*等待信号量*/     
    sleep (1);   
    /*临界资源*/ 
    gnum++;  
    printf ("Thread1 add one to num:%d/n",gnum);  
      
    sem_post (&sem);        /*释放信号量*/ 
 
 
       
  }     
}     
/*线程2的服务程序*/   
static void pthread_func_2 (void)     
{     
  int i = 0;     
    
  for (;;)     
  {     
    printf ("This is pthread2!/n");   
    sem_wait(&sem);     /*等待信号量*/ 
    sleep (1);  
    /*临界资源*/ 
    gnum++;  
    printf ("Thread2 add one to num:%d/n",gnum);  
      
    sem_post (&sem);        /*释放信号量*/ 
    
  }     
    
  pthread_exit (0);     
}

编译,运行,可以看出和上次互斥锁结果一样的

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/253431.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【leetcode】910. Smallest Range II

题目如下&#xff1a; 解题思路&#xff1a;我的思路是先找出最大值。对于数组中任意一个元素A[i]来说&#xff0c;如果A[i] K 是B中的最大值&#xff0c;那么意味着从A[i1]开始的元素都要减去K&#xff0c;即如果有A[i] K > A[-1] - K&#xff0c;那么A[i] K 就可以作为…

CMOS图像传感器架构的演变

01、 引言 图像传感器目前用于多种应用。自 1969 年电荷耦合器件 (CCD) 发明以来&#xff0c;固态图像传感器已蔓延到各种消费市场&#xff0c;例如小型摄像机和数码相机。自 2005年以来已成为主流固态图像传感器的 CMOS 图像传感器在为 CCD 开发的技术的基础上不断发展。除了…

Linux系统中/dev/mtd与/dev/mtdblock的区别

MTD(memory technology device内存技术设备)是用于访问memory设备&#xff08;ROM、flash&#xff09;的Linux的子系统。MTD的主要目的是为了使新的memory设备的驱动更加简单&#xff0c;为此它在硬件和上层之间提供了一个抽象的接口。MTD的所有源代码在/drivers/mtd子目录下。…

Python判断变量的数据类型的两种方法

2019独角兽企业重金招聘Python工程师标准>>> 1、isinstance(变量名&#xff0c;类型) def varargsql(self, sql, *args):if isinstance(args, tuple):self.cursor.execute(sql, args)self.conn.commit() 2、通过与其他已知类型的常量进行对比&#xff08;type()&…

svn图标的含义

http://www.cnblogs.com/genhaosan/articles/5129791.html 转载于:https://www.cnblogs.com/wangc04/p/6400477.html

基于事件的视觉传感器

在之前的文章里 人工智能与图像传感器_沧海一升的博客-CSDN博客_人工智能和传感器的关系第一类是图像传感器与人工智能计算相结合,即图像传感器模组除了可以输出图像之外,还可以直接输出人工智能算法计算的结果。另一类智能图像传感器则是为人工智能应用专门设计的图像传感器…

RocketMQ多Master多Slave模式部署

每个 Master 配置一个 Slave&#xff0c;有多对Master-Slave&#xff0c;HA采用同步双写方式&#xff0c;主备都写成功&#xff0c;向应用返回成功。 优点&#xff1a;数据与服务都无单点&#xff0c;Master宕机情况下&#xff0c;消息无延迟&#xff0c;服务可用性与数据可用性…

FPGA的ip核之概念和分类

ip核之概念和分类 IP&#xff08;Intellectual Property&#xff09;内核模块是一种预先设计好的甚至已经过验证的具有某种确定功能的集成电路、器件或部件。它有几种不同形式。IP内核模块有行为&#xff08;behavior&#xff09;、结构&#xff08;structure&#xff09;和物理…

codeforces 1045 D. Interstellar battle

题目大意&#xff1a;一颗树&#xff0c;给定每个点消失的概率&#xff0c;求出连通块的期望值。要求支持修改消失概率的操作并且给出每次修改过后的期望值。注意被破坏的点不能算入连通块中。 数据范围&#xff0c;时限1S。 传送门 D. Interstellar battle 我们考虑做有根树的…

RecyclerView(滚动控件)的用法

1.首先在build.gradle中添加依赖库 compile com.android.support:recyclerview-v7:24.2.1 2.修改activity_main.xml <LinearLayout ......<android.support.v7.widget.RecyclerViewandroid:id"id/recycler_view"android:layout_width"maych_parent"a…

Verilog中case(1‘b1)的使用说明

在用Verilog进行RTL代码编写的时候基本不会用到case(1‘b1)&#xff0c;而且一般的语法说明也如下&#xff1a; case(case_expr)condition1 : true_statement1 ;condition2 : true_statement2 ;……default : default_sta…

Cookie中文存储页面500问题

前段时间做cookie存储&#xff0c;直接用的菜鸟教程中的cookie设置方法&#xff0c;方法如下&#xff1a; function setCookie(cname,cvalue,exdays) {var d new Date();d.setTime(d.getTime()(exdays*24*60*60*1000));var expires "expires"d.toGMTString();docum…

Behave用户自定义数据类型

在step句子中, 所有的参数默认是string类型, 如果用户想使用复杂的或者其他数据类型, 就需要了解以下bahave中的数据类型. behave的数据类型转换器是在parse和cfparse中支持. parse模块是string.format的逆函数. parse_type是基于parse的扩展, 简化了自定义数据类型的产生. pa…

IC Compiler指南——数据准备

一、概述 ICC数据设置的文件关系框图如图&#xff1a; 后端工具在数据设置阶段需要对两大类数据进行设置&#xff0c;包括从前端设计继承的综合数据 以及后端设计需要的物理数据。 综合数据主要包括前端逻辑综合已经设置过的逻辑与时序库文件、设计约束文件sdc以 及综合网表文…

iOS Xcode全面剖析

前言 前几天在公司内部做了一次关于iOS的入门分享&#xff0c;听众有PHP、Web、Android、测试、产品、UI等&#xff0c;主旨是力求不懂iOS的人能了解iOS的开发流程&#xff0c;听后都能创建一个iOS项目并打印HelloWorld。&#xff08;这是背景&#xff09;你想想就这么点需求&a…

VS2013编译OBS源码

obs源码来之&#xff1a;https://sourceforge.net/projects/obsproject/ 下载源码之后直接打开sln索引文件就行 项目打开之后 obs作为启动项 直接编译就行&#xff0c;正常应该一下就能编译成功。 在运行的时候可能会报错&#xff1a; 这个问题就需要制定一下编译输出路径&…

Y/C分离/2/3D滤波器

待整理http://blog.csdn.net/yangzhifu/article/details/7388101 http://wenku.baidu.com/view/f997d705cc1755270722086d.html

构建之法阅读笔记04

敏捷开发是一系列价值观和方法论的集合。在敏捷的大旗下&#xff0c;我们可以看到好几种软件开发的方法论&#xff0c;我们在这里主要分析Scrum这个方法论。 从Scrum方法论中分析&#xff0c;敏捷开发一共分四步&#xff1a; 第一步&#xff1a;找出完成产品需要做的事情——Pr…

js图片切换

1.不同方式的图片切换 功能点:   1.页面默认循环切换,循环切换按钮获得焦点   2.点击顺序切换时,顺序切换按钮获得焦点     点击上一张时,当图片为第一张时,图片不再进行切换,图片张数和描述也不在变动;     点击下一张时,当图片为最后一张时,图片不再进行切换,图片…