301
社区成员
发帖
与我相关
我的任务
分享多线程设计中我采用了经典的消费者生产者模型,设计requestTable作为缓冲区来接收请求。在requestTable中就需要做到拿和取互斥,为此我将拿和取方法都上了锁确保线程安全。在后面的作业中requestTable中也会存一些共享数据,我也采用同步方法将读写共享数据都上锁。例如第七次作业中为了避免碰撞而设置标志位判断电梯能否进入中转层。


总体架构图如下:

时序图如下:

为了避免重构可能带来的风险,本单元作业没有对架构进行重构。根据开闭原则,第七次作业添加新类DoubleElevator来实现双轿电梯运行,避免修改导致普通电梯出现错误。
为避免电梯碰撞,在上下电梯共享的缓存区requestTable中设计标志位来标记是否有电梯在转运层。如有电梯停靠在转运层,则另一个电梯需等待电梯离开后改变标志位值后进入转运层。同时由于该标志位为两电梯共享,所以要考虑互斥问题,即两电梯不能同时操作该标志位,这一点在多线程设计中已有说明。

由于多线程的不可复现性,debug变得异常艰难,因为可能同一份数据在不同的地方出bug,这就无法精确定位bug位置。在单线程程序中我往往多次调试来逐步缩小范围确定bug位置,但这种方法在多线程程序中完全失效了,我觉得自己好像是在猜bug在哪,效率极低。通过这种方法熬了一个通宵后,我最终改变了debug的方法,即print大法。通过在关键地方print出状态信息来判断程序运行是否正确,这种方法确实有效,我很快就找到了错误信息。即使每次程序运行结果都不一样,但错误类型是一样的,这样就帮助我定位了bug位置。
多线程程序确实和单线程程序确实有很大区别,最大的区别就是它的不可复现性,这给我的debug带来了极大困难。最终我找到了适合自己的debug方法来调试多线程程序。关于线程安全方面我的感受倒不是很深,我觉得是因为java将多线程封装的太好了,只需按照设计好的方法编码就不容易出现什么问题。操作系统学到这部分时我才意识到多线程安全是个很复杂的问题,但这些问题需要编程者考虑的就比较少了。总体而言,我觉得按照规范的设计模式编码更不容易出现线程安全问题。