那天晚上,我看到@leekayak 同学AT我关于高并发lock-free
queue的问题,我做了一些回答,回想到自己找人一起干活很艰难,于是灵机一动,不妨搞个比赛,发掘人才。
于是第二天到了学校,申请了coderpk.com的域名,然后找了之前我写的一个lock-free
queue的代码,但是优化的太复杂了,大致看了下,就开始简化,然后就写网页,大概中午的时候推出,发布比赛。
很快,就有一个同学告诉我,他的笔记本20多秒就跑完了,我意识到肯定有问题了。我仔细看了下代码,发现了问题。后来我自己又发现了另外两个问题。这里一并交代。
1)队尾压队头(也就是队列满的问题),在我的设计中,如果没有出队,只有入队,那么循环一圈后,就会出现这个问题,这里采用了鸵鸟政策,也就是忽视,不做处理,因为在我拿来的这段代码的场合中,队列中的任务“总是”可以被及时的处理,只要队列长度足够长。
例如在龙泽城铁排队,只要队列设计的足够长,那么几乎不会出现队列满而后面排队的人要溢出队列。
这个问题怎么容易出现了?如果你笔记本低于8个核几乎很容易出现,因为10个入队操作先进入工作线程,而后面的出队操作很可能抢不到CPU,另外出队的操作比入队的复杂,所以就会有延迟,这样几乎很容易队列满,我的机器16核,所以出队基本能跟住入队,在缓冲区的这个长度下,所以不会出现问题。
2)hang住的问题,这个问题表现在大量的出队线程抢着CPU,而发现又没有东西入队,因此反复抢占,形成僵持。这个偶有发现。解决的方法是让出队操作发现僵持,并作出更多的退让。
3)队头压队尾,也就是当没有入队操作时,尾指针不动了,而头指针每出一次队就要向队尾靠近,为了避免超越,采用了安全距离规避,代码中写了一个魔数(20),但这样引入了一个问题,如果这个队列的入队操作是零星的,比如5分钟来一个,5分钟后来20个,那么这是第一个才会被出队,导致了大量延迟。
因为,这个队列的使用场景是高并发的(非用户队列),业务层的队列,入队的数据是持续的,大量的,高度均衡的,比如分词后的数据,推去做索引的这种。因此不会出现零星的入队情况。
不知道,我这么解释,是否解释清楚了。baseline是我写的,主要的问题如上,也无法再改了,提交的代码中@traits的第一版代码,也有队头压队尾的问题,我指出后他做了修改,另外一个获胜者也有类似问题,也修改好。就目前看,没有大的毛病,我认可了他们的成绩。
如果有其他同学质疑他们的代码,我认为能解释得通,将取消获胜同学的奖金。比赛后提交的作品,一律不参与奖金的活动,请同学们谅解,我确实没有时间继续支持这个活动继续的做下去。
其他的我不一一说明了,总之,这个代码写的仓促,我没有细想,第一次组织这种代码比赛的活动,没有经验,请大家谅解,希望以后有机会,有人帮助我一起搞这类活动,做一个公平的擂台,发掘码农的能力,公平竞技,展现风采。