猴子拿苹果问题-匿名信号量

马谦马谦马谦
马谦马谦马谦
马谦马谦马谦
611
文章
12
评论
2020年2月25日23:16:13 评论

一、猴子拿苹果问题

逛脉脉时,看到一网友遇到的面试题:有9个苹果,2只猴子。一个猴子每次拿2个苹果,一个猴子每次拿3个苹果。如果剩余的苹果数量不够猴子拿的数量,则停止拿苹果。请用多线程的方式模拟上面的描述。

看到问题的第一眼,觉得很有趣,脑海中第一个想到的就是通过信号量来实现,因为信号量是最适合做线程和进程状态同步了,而问题的考点就是线程同步。

恰好这两天刚好有在看信号量,所以很容易就想到通过信号量来实现这个问题。

其实原题说的是通过java多线程实现,但是我不会java,只能用c来写了。

为什么说考查的问题点是线程同步?因为题目要求是通过多线程来实现,如果不对线程状态制约,9个苹果,很容易在一瞬间就被一个猴子拿完,或许第二个线程还没开始苹果就已经拿完了。这明显不是面试官想看到的。所以不难想到考点就是如何协调两个猴子(线程)有序的拿桃子,有序的意思就是:你拿一次,我拿一次,要有次序的进行,直到把桃子拿完。如何控制线程之间你执行一次,我执行一次,肯定就要利用同步了。

二、匿名信号

匿名信号比较适用于线程间同步,因为它没有名字,所以多个进程间无法通过一个载体来共享它。只有在线程中,通过变量或者参数传递的方式来共享,所以适用于线程。

有名信号的用法参考:进程间通信之信号量

匿名信号的原理也和有名信号一样,维持一个计数器,然后通过等待计数器的状态来继续往下执行。相关的函数:

四个函数中,下面三个和有名信号量中的一样,唯一有区别的是第一个初始化信号量函数。匿名信号量无需传入信号量的名字,直接传入信号量对象就可以初始化了。后面的两个参数也都是一样,一个代表共享属性,一个代表默认值。

三、实现猴子拿苹果问题

两个猴子,肯定是需要两个线程,线程中辨别是哪个猴子肯定要传入猴子的参数,因此先实现一个猴子信息的对象,传入线程参数:

为什么需要两个信号量呢,逻辑是:我去拿猴子,拿完通知你拿,你去拿猴子,我等在这里,等你拿完通知我拿。一个是等待自己的信号量,一个是通知另外猴子的信号量,所以需要两个。

线程函数实现:

主函数实现:

执行结果:

猴子拿苹果问题-匿名信号量

过程描述:

  1. 第一个猴子拿2个苹果,剩余7个苹果。
  2. 第二个猴子拿3个苹果,剩余4个苹果。
  3. 第一个猴子拿2个苹果,剩余2个苹果。
  4. 第二个猴子想要拿3个苹果,但是苹果不够了,退出。
  5. 第一个猴子拿两个苹果,苹果被拿完。
  6. 第一个猴子想要拿2个苹果,但是苹果不够了,退出。
马谦马谦马谦
  • 本文由 发表于 2020年2月25日23:16:13
  • 转载请务必保留本文链接:https://www.dyxmq.cn/program/code/c-cpp/anonymous-semaphore.html
给socket分配随机端口 C/C++

给socket分配随机端口

客户端的socket不需要手动执行bind绑定地址,但这不意味着客户端socket真的不需要绑定端口,实际上是内核它帮我们做了这个操作,在执行connect时,内核发现没有绑定端口,就会自动选择一个合...
vector中emplace_back方法的用途 C/C++

vector中emplace_back方法的用途

在写代码的过程中,CLion提醒我把push_back方法替换成emplace_back方法: 代码中我的想法是使用vector创建一个二维数组,并提前分配好空间,避免后序频繁扩容增加时间复杂度。 e...
宏定义踩坑实战:嵌套调用宏定义 C/C++

宏定义踩坑实战:嵌套调用宏定义

问题背景:在刷题的过程中,要使用min函数,但是线上OJ并没有这个函数。因为一时也想不起它到底属于哪个头文件,所以为了偷懒,顺手就写下了以下宏定义: #define min(x, y) (x) <...
匿名

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: