301
社区成员
发帖
与我相关
我的任务
分享*:在三次电梯作业的实现中,三次架构的迭代关系较强,并未发生较为大规模的重构,所以以下关于三次作业的各种设计的分析将均以第三次作业的代码架构为准,不再赘述
synchronized(MissionAllotment){
...
void setEnd(...);
void addRequest(...);
boolean isEnd(...);
boolean isEmpty(...);
getOptimumRequest(...);
void pushMission(...);
...
}
在MissionAllotment中关于设定分配结束、判定分配结束、得到最最适应任务、分配最适应任务等方法均采用了同步块的设置,并将锁设置在了MA,这样做是为了防止读取数据和更新数据同时发生,从而导致无法正常同步的问题
synchronized(ElevatorThread){
...
void addResetSignal(...);
void addDoubleResetSignal(...);
boolean isReady(...);
void setEnd(...);
void setPriorityKey(...);
getMainMission(...);
boolean isEnd(...);
boolean isEmpty(...);
void StrategyApply(...);
...
}
synchronized(SubElevator){
...
boolean suitable(...);
boolean limited1(...);
boolean limited2(...);
...
}
关于对ElevatorThread和SubElevator的处理,有关于新任务的push和主任务、电梯状态的读取等,均采取了加锁的策略来保证其同步,并且在MissionAllotment中对于此类事项的处理亦是如此,其目的在于防止电梯相关信息的读取与电梯状态的转换同时进行,这样可能会导致电梯状态和数据的错乱
synchronized(Total){
...
void addSum(...);
void addFinishedRequest(...);
boolean isDone(...);
...
}
Total一类是用于实现对输入任务的完成情况的判断判断和读取的,其功能类似于仪表盘,因此在实现中,有关于对Total中的任务数量和已完成任务数量以及任务完成情况的修改和读取均需要加锁,其原因在于该类将会被InputThread、SubElevator、ElevatorThread等类共享,在整个进程运行的过程中,有可能会发生以上不同对象对于此类数据同时修改+读取的情况,必须采用同步块来杜绝其发生
synchronized(TransferFloor){
...
void occupy();
void release();
boolean isOccupied();
...
}
TransferFloor的设置是用于避免双桥厢电梯相撞的问题,因此其状态的改变和读取必须加锁,并且在StrategyMap中有关其状态的修改的语句也必须如此


较为稳定的内容
Main中对于各类线程的创建过程与链接组合
MissionAllotment对任务的接受与分配,以及其关于捎带逻辑的判定和对适宜任务的挑拣
InputThread中接收标准输入的逻辑与分别对6个MissionAllotment对象分配请求的逻辑
ElevatorThread中电梯运行的基础逻辑基本维持不变
易发生变动的内容
InputThread对任务完成反馈情况的反应部分,在第二第三次作业中由于Reset和双桥厢电梯的存在,使得部分分配后的任务将无法直接实现,此时需要如Total类等措施来将未完成的任务再分配
StrategyMap中对如Reset或双桥厢转换情况下的电梯变动策略,尤其是在第三次作业的迭代中,因为需要考虑到桥厢相撞的情况,此时甚至需要新设立一个TransferFloor的类并依赖于其occupy功能来避免相撞
要想避免两个桥厢相撞,即是当其中有一个桥厢位于转运楼层时,另外一个电梯不可进入转运楼层,这也就意味着如果不借助外部条件的话,则必须要实现两个桥厢之间的同步通讯,在实现的过程中,我有尝试过利用直接建立二者的通讯,然而这也使得我们需要在一个桥厢进出转运楼层时候,需要给另一个桥厢加锁,这严重背离了常理判断和类与对象的实现原则,因此该想法被废除,最后我们实际上是建立了一个新的单类TransferFloor来实现这一功能,即每当电梯进入该楼层时,将会取得TF的锁并调用其occupy()方法,当isOccupied变量为True时,另一个桥厢自然无法正常进入,并且我修改了StrategyMap中电梯处于Closing时的状态转换逻辑,使得当电梯位于转运楼层时,会以最快的速度离开该楼层,并调用release()方法,避免了一个桥厢独占转运楼层的情况
在实现过程中,最常出现的BUG便是CTLE,其大多是因为轮询,在前两次作业中,其主要出现形式是一直询问是否存在请求,这样的bug只需合理使用wait()方法并在合理的时间段释放电梯的锁以接收可能到来的请求即可避免,而第三次作业中出现的bug则较为特殊,其是因为我们在实现逻辑中,采用了MA和ET之间相互唤醒这一方式,这会使得我们在前文提到的已经设立好的wait()方法被频繁唤醒,进而使得轮询的再次发生,我们最后给出的解决方案是,设立好Total类与ET中的变量mark,从而保证当这种情况发生时,我们可以利用设立好的mark来保证这种互相唤醒的状态将会以有限的次数发生,并且有了Total类的参与,我们可以更加灵活地记录各个任务的完成情况,避免了死锁
在该单元中,我们学习了多线程的各类概念与多线程问题的解决方式,可以说是OO系列课程中最难的一单元,而在这个月中,OS课也刚好位于进程与线程这一部分,可以说二者知识层面的结合与交互,切实让我受益匪浅,使得我能同时从理论和应用的角度去真正意义上学习解决多线程问题,我相信这对我未来的编程方面的学习来说也是意义非凡的,最后我希望感谢这一单元的助教团队和课程组教师的辛勤付出,谢谢你们共同奉献了如此优质的教学内容,故余虽愚,卒获有所闻