OO多线程debug第二篇---如何定位bug

1. 输入条件的bug

这周OO第二次多线程电梯作业,我这次吸取了上周的教训,周三开始动工,周四就搞定,并顺利通过本地和网站的自动测评机的正确性测评。

在周四的自动化测评中找出如下bug:

  • 电梯进程的结束条件错误: 我原先定的结束条件是input进程结束并且当前电梯进程的pin和pout队列为空。但是这用做可能会漏掉最后的输入,因为当最后的输入p被添加到全局pout队列,然后input进程结束。若这时候电梯的pin,pout队列恰好为空,而在controller进程把p添加到电梯的pout之前,电梯进程就结束了,然后p被添加到电梯的域pout(因为进程虽然结束,但是电梯这个实例还存在),然后p就永远不会被搭载。

我吸取的经验是:若多线程的多个线程的输入之间相互依赖: Aout -> Bin,
Bout -> Cin。 那么B结束的条件是A结束且B处理完当前数据; C结束的条件是B结束且C处理完当前数据; C不可以跳过B而已A的结束作为结束条件。

2. 代码处理数据的逻辑的瑕疵

之后笔者在周六用小黄鸭测试法检测了一遍代码,找出了代码逻辑中关于maxfloor和minfloor取值的小瑕疵,修改后代码性能更优。

又找出了二次assign算法的瑕疵,将第二次分配调整为以distance为度量标准,优化了性能。

3. 线程的同步互斥保护

观察了在网站上我的反馈结果和本地测评机的结果,发现我的电梯的上下楼时间和开关门时间远远大于0.4s. 最后通过print大法, 发现是我将elevator的sleep放在了synchronized代码块里。导致长其中某个elevator长时间占有锁,这个elevator结束后,另一个elevator又长时间占有锁,导致某些需要锁来执行指令的elevator长时间得不到锁。

4. 多次提交网站发现的bug

我多次提交网站后,发现我WA了。原因是我先start了controller线程,这里面要调用elevator的addPout方法,但addPout方法加了controller的锁。但我是在start Controller后面才为elevator设置了Controller实例域,因此执行到contrller run里面的elevator.addPout时,就可能报空指针错误(锁不能为空指针)。因此,尽量现在开头把各种实例的实例域都设置好,最后再start线程。

5. 总结

  • 小黄鸭测试法非常重要,一定要做;小黄鸭测试法和性能检查和线程安全都要在周五之前完成检查,这样才有时间修改

  • 观察本地和网站输出结果的时间间隔

  • print大法

  • 避免将sleep,join和长耗时的计算放在synchronized代码块里(可以设置标志位将这些耗时的代码移到监控区外),因为这样的话执行这个代码块的线程会长时间持有锁,导致其他进程都处于阻塞或wait态;wait可以放在synchronized代码块里,因为wait会交出锁。

  • 一个好的多线程程序,在线程overview里,它的running进程数和waiting进程数一定是平稳变化的; 若进程数变化杂乱无章,极有可能线程与monitor有问题。

  • 尽量现在开头把各种实例的实例域都设置好,最后再start线程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值