第二单元博客作业

早就听闻多线程玄学而神秘,刚上手的时候疯狂上锁把共享资源藏得严严实实的勉强保证了线程的安全性,但到了后来线程间同步和互斥关系更加复杂,终于还是入了线程不安全的坑…最直观的就是在第三次的时候,互测挨了两刀但本地怎么也复现不了,结果直接提交原码后互测点全过了,但强测点却错了俩…解决了线程不安全的问题之后,总算是过了所以点…(幸亏强测的时候脸好没挂)

言归正传。

(一) 从多线程的协同和同步控制方面,分析和总结自己三次作业的设计策略。

1.1第一次作业要求较简单,只要求实现简单的目的选层电梯,不考虑优化的话,只要电梯能接人、能正常切换楼层、能放人出去就基本满足了要求;考虑优化的话…好像也没什么可优化的。大体思路就是输入单独开线程,电梯单独开线程,两线程间共享对象为候梯人队列。

1.2第二次作业在第一次作业的基础上加入了“可捎带”的要求,整体的设计思路不需要大改,只需要对电梯的运行模式进行调整。具体的操作可以是加设控制器,为电梯设定+更新目的地/运行方向也可以是在电梯内部新建方法,实现捎带人的功能。非动态调度的可捎带人的电梯算法大概有FCFS,SSTF,SCAN,LOOK,SCFT几种,在以总运行时间为考量标准的前提下,LOOK算法性能较优且稳定。我选择了在电梯中实现“更新目的地”方法,并采用LOOK算法。同作业一,共享对象为候梯队列,加锁即可。

1.3第三次作业不但增加电梯数量至三台,还从载客量、运行速度、可停靠楼层等方面限制了电梯的发挥空间。我选择在实现三台LOOK电梯的同时考虑三台电梯的负荷。具体的操作就是:单独开线程读请求,读到的请求首先写入queue1,若存在转乘情况则转乘请求写入queue2(如from-1-to-16,可分为from-1-to-15和from-15-to-16),开调度器线程逐条处理请求,当遇到出发楼层为-3或大于15层时,请求分配给A电梯,保存转乘请求,当出发楼层为3层时,交给C电梯,其他情况下,当目的地为-3或大于15层时,考虑A的位置及运行方向(是否需要单独为此请求跨越整栋楼)和A的负荷情况,当二者有一个不满足时,依次考虑B、C能否捎带至15层(或1层),若均满满载或不顺路(请求从1层出发,而B刚来到2层并且在向15层移动等情况),则分给A,否则分给B或C;当目的地为3时,考虑C的负载和顺路情况,必要时由B将请求运送至2或4再转C电梯;当目的地为-2/-1时,除非B满载且C有余额(交给C捎带至1层),否则交给B,其他情况下,考虑B、C的运行位置、方向以及负载情况,以B为主以C为辅,但不将C视作B的备胎,在B不顺路,C可捎带时分给C。

(二)基于度量来分析自己的程序结构

第一次电梯:

第二次电梯

 

第三次电梯

 

第三次作业中很多方法的复杂度较高,主要是因为“面向对象”程度不够“,很多功能并没有完美的分离开,下一步目标是在打代码前在一定程度上规划好体系,防止过程中发现架构有问题再匆忙修改各方法。

(三)分析自己的bug

第一次作业较简单,线程间同步互斥关系简单,在第二次的时候由于需要考虑捎带和电梯的重定向,所以说对队列的读写和对电梯状态的修改容易出现不安全的问题,在课下调试自己代码的时候出过问题,幸而得到了解决。第三次吸取了第二次的教训,没有出现线程不安全的问题,但是在拆分指令的时候由于没有完整地规划好,导致出现了from-1-to-1的情况,出了些bug(发现进程无法停止,花了些功夫才定位到这个问题)。

(四)发现别人bug的策略

经过互测,发现别人身上出现的问题大体和我一样有两类:线程不安全和指令处理有误。线程不安全的问题未必能百分百复现,一时半会可能都发现不了,发现了也未必能揪出来,指令处理有误的问题其实只需要覆盖性的测试就必然能发现。

(五)心得体会

虽然说距上次博客作业才刚过了不到一个月,但是我对面向对象的认识却已经有了不小的进步。无论是对多态和继承的使用还是打代码都越发得心应手起来。只是目前对线程安全性的把握仍然不够准确,很多时候依然拿捏不好上锁的对象和位置。老师说共享对象是一个房间,某某线程进来后不能再有线程进来捣乱,要锁上某个房间并不难,难的是在保证除这间房间外的其他房间不受此影响。回看原先的代码,很多时候我都是通过锁住整间房子来达到锁房间的目的,这也是我下一步要不断探索解决的问题。

此外,老师还提出:①应该在共享对象中进行访问控制,而不能在线程类代码中实现 ②在run中不应展开细节→推荐在方法中加锁,而不是在调用方法的外部。这同样是我要注意的问题。

猜你喜欢

转载自www.cnblogs.com/hiahiahia/p/10753943.html
今日推荐