深入理解 Go 语言信号量 Semaphore

news/2024/9/23 7:58:14/

1. 什么是信号量

        信号量的概念是荷兰计算机科学家 Edsger Wybe Dijkstra 在 1963 年左右提出来的,被广泛应用在不同的操作系统中。在操作系统中,会给每一个进程分配一个信号量,代表每个进程目前的状态。未得到控制权的进程,会在特定的地方被迫停下来,等待可以继续进行的信号到来。

        Edsger Wybe Dijkstra (1930-2002) 是一位荷兰计算机科学家和数学家,被认为是计算机科学领域的先驱之一。他在计算机科学的发展史上发挥了重要作用,他提出的算法和思想对计算机科学和软件工程产生了深远影响。

        Dijkstra 最为著名的贡献之一是开发了 Dijkstra 算法,它是一种在图形网络中找到最短路径的算法,被广泛应用于网络路由和其他领域。他还发明了一种名为 “信号量” 的同步机制,为并发网络编程提供了一种重要的工具。此外,他还对程序设计语言的诘法和结构进行了深入的研究,为编程语言的设计和实现提供了许多有价值的建议。

        Dijkstra 也是一位重要的教育家和思想家,他强调了对计算机科学教育的重视和深入思考的重要性。他在其许多著作和演讲中都强调了算法与程序设计的重要性,并强调了开发高质量软件的必要性。

        Dijkstra 在他的职业生涯中获得了许多荣誉,包括图灵奖、IEEE 计算机协会的计算机科学和工程奖、ACM SIGPLAN 的系统软件奖等。他去世后,他的贡献得到了计算机科学领域的广泛赞誉和纪念。

        最简单的信号量是一个变量加一些并发控制的能力,这个变量是 0 到 n 之间的一个值。当 goroutine 完成对此信号量的等待(wait) 时,该计数值就减 1 ;当 goroutine 完成对此信号量的释放 (release) 时,该计数值就加 1。当计数值为 0 时, goroutine 调用 wait 等待该信号量是不会成功的,除非计数值又大于 0 ,等待的 goroutine 才有可能成功返回。 

1.1 P/V 操作

        Dijkstra 在他的论文中为信号量定义了两个操作 : P 和 V 。P 操作(如 decrease、wait、acquire) 用减小信号量的计数值,V 操作(如 increase、signal、release)则用来增大信号量的计数值。

        P ( passeren)在荷兰语中表示 “通过” ,V (vrijigeven) 在荷兰语中表示 “释放”,这也许就是 Dijkstra 把它们叫做 P/V 操作的原因。

        使用伪代码表示如下(方括号代表原子操作):

Go">function V(semaphore S, integer I):function P(semaphore S,integer I):repeat:[if S ≥I:break]

        可以看到,初始化的信号量 S 有一个指定数量 (n) 的资源,它就像一个有 n 个资源的池子。P 操作相当于请求资源,如果有足够的资源可用,则立即返回;如果没有资源或者资源不够,那么它可以不断地尝试或者被阻塞等待。 V 操作相当于释放资源,把资源返还给信号量。信号量的值只能由 P/V 操作改变(初始化操作除外)。

现在,我们来总结一下信号量的实现。

  • 初始化信号量:设定资源的初始数量。
  • P 操作:将信号量的计数值减 k,如果新值为负数,那么调用者会被阻塞并加入等待队列中;否则,调用者会继续执行,并且获得 k 个资源。
  • V 操作:将信号量的计数值加 k, 如果先前的计数值为负数,则说明有等待的 P 操作的调用者。 V 操作会从等待队列中取出一个等待的调用者,唤醒它,让它继续执行。
1.2 信号量和互斥锁的区别与联系

        信号量有两种类型:二元信号量和计数信号量。其中,二元信号量只有两个值,通常是 0 和 1,它用于


http://www.ppmy.cn/news/1505516.html

相关文章

回顾前面刷过的算法(4)

今天回顾一下下面三个算法,涉及到了动态规划、合并链表、位运算,好吧,让我们再次手敲一遍 //乘积最大子数组//思路: 维护三个变量,imax最大前缀乘积 imin最小前缀乘积 max最大连续乘积//由于元素有正负,imax和imin需…

vue2项目如何引入element组件库以及如何使用element组件库

目录 一、创建项目二、进入项目1、先进入项目,![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/a1ce9d928fdb4b5d85e6612f458a33db.png)2、路径栏输入cmd,然后回车3、输入code . ,然后回车 三、项目启动1、查看启动指令2、启动项目 …

Android ImageReader获取YUV数据

这个函数以一个 Image 对象作为输入,并返回一个包含 YUV 数据的 ByteArray fun image2YUV(image: Image): ByteArray? {// 计算 Y 组件(亮度)的大小val ySize image.cropRect.width() * image.cropRect.height()// 计算 UV 组件&#xff0…

使用Adobe Photoshop CS5给图片加水印

使用Adobe Photoshop CS5给图片加水印 前言1.我这里使用的是Adobe Photoshop CS52.新建空白画布3.写入水印内容4.按 Ctrl T 将其倾斜5.右键图层选择“混合选项”6.选择描边,颜色选择灰色7.效果如下8.填充选择0,不透明度选择75%9.打开编辑,选…

【C++】string类

🚀个人主页:奋斗的小羊 🚀所属专栏:C 很荣幸您能阅读我的文章,诚请评论指点,欢迎欢迎 ~ 目录 前言💥1、标准库中的string类💥1.1string类的常用接口💥string类对象常见…

实验10 任何一个非0自然数m的立方均可写成m个连续奇数之和。

实验10 题目描述 任何一个非0自然数m的立方均可写成m个连续奇数之和。 例如: 1^3 1 2^3 35 3^3 7911 4^3 13151719 编程实现:输入一自然数n,求组成心的n个连续奇数。 【实验要求】 1、不允许用等差数列的方法求首项 2、要求使用双重循环&a…

uniapp上架安卓市场(小米、华为、魅族)部分问题

隐私弹窗 首先选择原生隐私弹窗 勾选后会在项目中自动添加androidPrivacy.json文件,可以双击打开自定义配置内容,以下内仅供参考: {"version" : "1","prompt" : "template","title" : &…

学习笔记第二十天

1.缓冲区 1. 1行缓冲(Line Buffered) 应用场景:主要用于与终端(terminal)的交互,如stdout(标准输出)通常就是行缓冲的。 缓冲区大小:通常不是固定的,但可以通…