BUAA_2024_OO_第二单元博客作业

张学东-22373307 学生 2024-04-20 19:05:28

第二单元主要进行了多线程的学习,重点内容是解决线程安全问题。

三次作业的分析:

第一次作业:

设计思路与类图

img

第一次作业的架构相对简单基本为生产者消费者模型。

MainClass中生成了6个Elevater线程和一个InputHandler线程,同时为每个Elevater生成了一个RequestTable作为请求处理

Outputhandler为输出工具类,其中都是static方法,为输出提供公开方法。

每个Elevator在创建时会生成一个内置的调度器,调度器里面有RequestTable和Elevator的全部信息,采用Look算法,为电梯提供策略。

电梯收到相应的策略后,会依照策略执行相应的动作。

同步块和锁的设计

第一次作业相对简单使用synchronized 关键字实现同步互斥,简单来说,就是在RequestTable中的所有方法加入synchronized,确保Elevator在读写相应的数据时,InputHandler不会把新的数据写入。

调度器设计:

采用look算法,look算法相比ALS算法更为优化,减少了无效运输的部分

UML协作图:

img

BUG分析:

第一次作业相对简单,没有出现bug,也没有hack到人。

第二次作业:

设计思路与类图:

img

第二次作业相对复杂了一些,在第一次作业的基础上:

  • 增加了总调度器Allocator
  • 增加了总的 AllRequestTable
  • 每个电梯配置一个ResetTable,用来临时存放Reset请求

同步块和锁的设计:

第二次作业对于锁的设计思路与第一次作业一致,

在会产生读写冲突的地方ResetTable和所有的RequestTable中加入synchronized关键字

为了避免结束时死锁的发生,在结束时会对所有可能有锁的地方进行notifyAll,防止InputEnd后电梯陷入等待

调度器设计:

第二次的调度器采用母子调度器,每个电梯上配置的小调度器采用look算法。

母调度器根据子电梯的性能、人数等打分,选择最优的电梯,把Person从AllRequestTable移动到该电梯的lRequestTable,进行请求分配。

电梯在Reset时会把所有的人重新放回AllRequestTable中(如果到了目的地,直接结束即可)

UML协作图:

img

BUG分析:

第三次的bug出现在没有为正在Reset的电梯设计buffer,即其优先级过低。如果其他5个电梯都在Reset,此时所有请求都会进入同一个电梯,造成TLE。

修复:增加buffer,如果分配到Reset的电梯,先放入buffer,等reset结束,从buffer中移动到相应的table并输出receive

第三次作业:

设计思路与类图

img

第三次作业和第二次作业相比,有如下改动:

  • doubleCarElevaror 继承自Elevator类,增设相应方法和数据
  • 为每个双轿厢电梯重写 DoubleCarScheduler
  • 为了方便Allocator等获取电梯停转、电梯数据等信息,增加Collection类,里面存放了取得各种Elevator信息的static方法

同步块和锁的设计:

与第二次作业相同,Table类全部使用上锁方法。

把ResetTable从synchronized改成readwritelock,因为ResetTable读的频率远大于写,这样提高cpu性能。

调度器设计:

简化设计,母调度器采用mod6的方法依次分配到相应的电梯井的RequestTable

电梯井收到后判断应该是A或B电梯运输,输出相应的Receive

对于双轿厢电梯 ,每个电梯的子调度器的顶楼设计从11层改为过渡层,如果目的地超出过渡层就把乘客放在过渡层,交给Allocator重新分配。

0本次设计为确保正确性和稳定性,一定程度上不是最优性能分。

UML协作图:

img

BUG分析:

第三次作业bug原因:结束时只看了所有PersonReset的finish,没有看双轿厢电梯的ResetFinish。

debug:增设双轿厢电梯ResetFinish信息的Hashmap,存放在Collection中。

双轿厢电梯防撞设计:

在DoubleCarScheduler进行分析判断,作出如下设计:

  • 首先电梯不能在过渡层中wait,如果没有请求,应当先判断是否处于过渡层中,如果是先退出,之后再判断能否wait
  • 在两个电梯共用的requestTable中加入occupy变量,如果一个电梯要往过渡层移动,occupy记录为true,如果另一个电梯想要往过渡层移动,该电梯必须进行OccupyWait

心得体会

第二单元学习了多线程安全,同时又深化了层次化设计的理解。

在线程安全方面,我们的bug主要出现在多并发的情况,结合老师上课讲的案例,我们在写多线程时应当时刻有多个线程的感觉,而不是写单一的程序。

同时,层次化设计为线程安全提供了保障,可以通过层次化设计,减少bug的出现,减少迭代过程中的复杂程度。

一味地追求性能分有可能不如确保程序的安全稳定运行更重要

...全文
96 回复 打赏 收藏 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

301

社区成员

发帖
与我相关
我的任务
社区描述
2023年北航面向对象设计与构造
学习 高校
社区管理员
  • YannaZhang
  • CajZella
  • C_ecelia
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧