16 Jan 2016
Semaphore是多线程编程时一个很重要的概念,概念本身并不复杂,但要做到正确使用却不容易。这里我们从面向对象的角度来理解这个概念。现实生活中的任何对象或实体,我们都可以用class来描述它。Semaphore也不例外,如果用class定义应该是这样:
Semaphore对象里包含一个count值和一个队列对象,另外有两个对外public的方法,wait()和signal(),需要特别注意的事,count值代表的资源数量是不能为负的。为了理解这些属性和方法,我们可以类比一个现实生活中的例子。大家去餐厅吃饭,假设这个餐厅有10个座位,有20个吃货随机出发去这个餐厅吃饭,那么对应关系是这样的:
这其实是一个信号量应用的典型场景,这里关键在于正确理解wait和signal发生时都有哪些细节步骤。用代码来描述大概是这样:
具体到餐厅到例子,20个人随机出发去餐厅吃饭,有10个人先到,然后挨个执行wait。前10个人执行wait的时候是有位置的,所以count>0,这10个人每人都消耗掉一个座位开始吃饭。到第11个人到了都时候,count==0,没有位置了,所以被suspend,开始加入排队都队列等待。后续所有人都慢慢的到来,但和第11个人一样,都只能排队。
过了一段时间之后,有个人吃好结账离开了餐厅。这时候如果没有人在排队,位置数量count ++,没有其它事情发生。但如果有人在排队,比如上面的情况,有10个人在等待位置,餐厅会把排在第一个的人安排到刚才空出来的位置,count值没有变化,但队列的人少了一个。
对于wait和signal还有两点需要特别注意。也是平时我们使用semaphore时比较容易产生bug的地方。