博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
理解PV操作和信号量
阅读量:6912 次
发布时间:2019-06-27

本文共 2485 字,大约阅读时间需要 8 分钟。

hot3.png

对于信号量,可以认为是一个仓库,有两个概念,容量和当前的货物个数。

P操作从仓库拿货,如果仓库中没有货,线程一直等待,直到V操作,往仓库里添加了货物,为了避免P操作一直等待下去,会有一个超时时间。

V操作往仓库送货,如果仓库满了,线程等待,直到有P操作,从仓库中拿走货物,有空的位置。

创建信号量,设置容量,先有V操作,才能P操作。

 

P操作:货物个数减1,减过之后,货物个数大于等于0,说明已经拿到货物,线程继续。否者线程阻塞。

V操作:货物个数加1,加过之后,货物个数小于等于容量,说明添加成功,线程继续。否者线程阻塞。

信号量:0≤ 信号量≤容量 ,取值 表示当前可以使用的货物;

        信号量<0 ,  取值 表示当前等待使用货物的线程;

            信号量>容量 ,  信号量-容量 表示当前等待添加货物的线程。

通常,信号量的容量设置很大,可以一直V操作,不会阻塞,但是P操作的时候,很可能阻塞。

当容量为1,也就是互斥,执行流程必定是V操作,P操作,V操作,P操作...


信号量如何做到线程同步?

可以认为信号量关联一组线程,保存一个指针,指向线程数组的首地址。比如当前信号量为-1,进行P操作,信号量为-2,说明没有拿到货物,线程等待,取值为-2,说明有两个线程等待那货物。这个时候,其他线程进行V操作,信号量加1,为-1,信号量通知等待的线程中,第一个线程继续执行,第二个线程继续等待。

也就是说,P操作等待的情况是减1后,信号量小于0。 P操作继续执行的情况有两种:a、减1后,信号量大于等于0,不需等待,直接执行;b、信号量小于0,等待中,其他人进行了V操作,通知这个线程,继续执行。


项目中的使用场景:

客户端使用提供的SDk与服务交互,为了提高效率,客户端发送一个请求后,SDK异步回调给客户端。但是,有些请求,客户端希望同步,等待回复。这个时候,建立一个map,以req的sequence为key,value为信号量的指针,信号量的容量设置为1,可用的货物为0,对信号量进行TimeoutP操作,货物个数为-1,阻塞在这里。异步回调,收到回复的sequence,根据map找到信号量指针,进行V操作,货物个数为0,通知前面TimeoutP的线程继续执行下去,这个时候,TimeoutP的线程,把回复消息取出来,返回给客户端。

对信号量最基本的操作就是进行PV操作,而System V信号量正是通过 semop 函数和 sembuf 结构体的数据结构来进行PV操作的。

当 sembuf 的第二个数据结构 sem_op 设置为负数时,是对它进行P操作,即减1操作;当设置为正数时,就是进行V操作,即加1操作。

      
 下面举一个对一个信号量集中的某个信号进行 PV 操作的函数实现:

//P操作函数        int  sem_p( int semid, int index )        {                  struct  sembuf  buf  = { 0, -1, IPC_NOWAIT};                                    if ( index < 0 )                  {                                 perror ( "index of array cannot equals a minus value!\n" );                                 return  -1;                  }                  buf.sem_num = index;                  if ( semop ( semid, &buf, 1) == -1)                  {                                perroe ( " a wrong operation to semaphore occurred!\n" );                                return  -1;                  }                  return  0;        }        //V操作函数        int  sem_p( int semid, int index )        {                  struct  sembuf  buf  = { 0, 1, IPC_NOWAIT};                                    if ( index < 0 )                  {                                 perror ( "index of array cannot equals a minus value!\n" );                                 return  -1;                  }                  buf.sem_num = index;                  if ( semop ( semid, &buf, 1) == -1)                  {                                perroe ( " a wrong operation to semaphore occurred!\n" );                                return  -1;                  }                  return  0;        }

 

 

转载于:https://my.oschina.net/aslanjia/blog/699830

你可能感兴趣的文章
P499 usebrass2
查看>>
matrix-gui-browser-2.0 matrix-browser Qt QWebView hacking
查看>>
OC中的 延展
查看>>
windows2008吃尽内存的解决办法
查看>>
JS去遍历Table的所有单元格中的内容
查看>>
LeetCode解题思路:3. Longest Substring Without Repeating Characters
查看>>
FontMetrics属性的介绍
查看>>
mysql 时间戳
查看>>
HDU 4734 F(x) DP, 数位DP
查看>>
剑指offer 快速排序
查看>>
Codeforces 894 A B 组合数学 比赛
查看>>
Python学习
查看>>
[1480]数据结构实验:哈希表 sdutOJ
查看>>
Entity Framework的启动速度优化
查看>>
C# .NET Socket封装
查看>>
SQLServer随机取记录
查看>>
Python数据结构与算法
查看>>
vim插件ctags的安装和使用
查看>>
C语言面试题汇总之一
查看>>
linux重新设置密码,亲试成功
查看>>