• Welcome to the world's largest Chinese hacker forum

    Welcome to the world's largest Chinese hacker forum, our forum registration is open! You can now register for technical communication with us, this is a free and open to the world of the BBS, we founded the purpose for the study of network security, please don't release business of black/grey, or on the BBS posts, to seek help hacker if violations, we will permanently frozen your IP and account, thank you for your cooperation. Hacker attack and defense cracking or network Security

    business please click here: Creation Security  From CNHACKTEAM

Recommended Posts

Unit 2总结

一、第一次作业

该作业采用生产者-消费者结构,整个电梯系统主要由一个总调度器(Scheduled)、一个InputThread(输入线程)、一个电梯线程类(Elevator)和一个等待队列(PassengerQueue)组成。的一般实施过程包括以下两个级别:

1、输入线程——等待队列——调度

这个级别的功能是解析输入线程输入的数据,并将其放入waitingQueue。之后,总调度程序可以从等待队列中取出乘客数据,在内部进行调度,并将其分配给不同的电梯线程。其中的共享对象是waitQueue。

2、调度——乘客队列——电梯

这个层次的作用是实现调度程序和电梯线程的交互。因为每个单元1只有一部电梯,所以只需要在MainClass中打开5个PassengerQueueu作为共享对象,不需要额外的补充。所以我在第一次赋值的时候有点懒,以至于第一次赋值代码的伸缩性很差(后面总是要返回)。

除了生产者-消费者模型,第一个作业的重点是电梯线程的编写。因为第一次作业比较简单,说明书上的要求比较详细,需要自己展开的东西不多,只要按照说明书写就可以了。个人认为,难点在于解决民调的问题。轮询是一种总是执行某个周期,导致CPU资源过度使用的方法。问题可能是在进程应该结束的时候,因为不满足某个条件而无法结束,同时又没有其他手段可以暂时停止线程循环,于是就产生了轮询。

有两种方法可以解决轮询。第一种相对比较棘手,就是可以使用sleep()语句,让循环在条件不满足时等待。二是保证无论哪条执行路径,每个while循环中都会有一条使线程进入等待状态的语句,这也可以解决轮询问题。

第二个难点是捎带。如果严格按照ALS调度策略,很可能出现以下情况:第一个乘客需要从10楼到1楼,其他乘客分别是1-10和2-10.使用ALS会导致性能下降。

二、第二次作业

与第一次作业相比,第二次作业增加了一部水平电梯,增加了对电梯的需求,同样难度不大。

我还是用一个电梯类作为水平电梯的处理方式。在电梯类中,通过判断电梯型号来运行两种不同的运行方式,电梯型号也决定了电梯对应的PassengerQueue。

添加电梯需要在输入线程中修改。当输入线程检测到电梯添加请求的指令时,会找出电梯类型对应的PassengerQueue,同时根据楼层和建筑区分水平电梯和垂直电梯。

增加电梯后,会出现多部电梯共用一个乘客队列的情况。我采用自由竞争的方法。为了解决资源竞争的问题,这里不得不提到同步块和锁。

同步块与锁

让我们看看下面的代码。

gqkcot4ir015206.png

同步锁用于同步块,try-catch用于处理异常。

在这个单元的过程中,我对锁的理解有以下两个方面。

1.所有的锁都应该在used类中完成,而不是用户,这大大提高了代码的可伸缩性和安全性。

2.第二,在PassengerQueue中取乘客时,取和删除两个操作必须同步完成,用户不能先调用get方法再调用remove方法。如果使用这种方法,很可能两个线程会同时获得同一个乘客,然后删除两个乘客,从而导致错误的答案。

同时,PassengerQueue中还提供了isEnd、isEmpty等方法。这些方法需要被锁定以避免问题。

三、第三次作业

与前两次运营相比, 的第三次运营增加了对定制电梯的需求,同时,乘客可以提出跨楼层和跨建筑物的移动请求。

电梯的定制需求只需要修改原始睡眠中的数据和最大载客量。如果前两个操作扩展性更好,代码不含“幻数”,实现起来更方便。

跨楼移动需要使用流水线模式,虽然我不完全做。先说说我的做法。

我修改了我的原始乘客类,如下所示

原始版本:

3681-20220503194533864-460271581.png" width="468"/> 

新版

n2yelh4tt2g5207.png

可以看到我将原来的startBuilding、endBuilding都替换成了ArrayList的形式,原因在于我可以在输入线程中读取到需要换乘的乘客时,根据我维护的一张电梯可到达楼层楼座图来规划出我的乘客换乘路线,并且保存在这几个数组中。同时,我将几个get方法修改成了读取ArrayList的第一位,这样我原来的代码并不需要改变,只需要在乘客出电梯门的时候判断乘客是否已经到达目的地,如果未到达目的地且当前需要换乘,就调用next方法将已完成的任务删去,这样重新get的结果就是原来ArrayList中的第二项,也即新的任务。在判断是否到达目的地我使用了变量nowNum和stageNum来记录,stageNum为输入线程设置的,nowNum为当前完成到了那一步,由电梯线程进行修改。

 ij4cxgms2rl5208.png

经过以上的处理之后,在将新的乘客直接丢入到waitQueue中,采用上述的方法可以不用建立一个新的乘客,产生变化的原因仅仅只是因为我的几个get方法拿到的数据发生了变化。这样就实现了跨楼层和楼座请求的换乘问题

 

UML类图

 vogh4uoeepc5209.png

 

 

协作图

 kfnh2ndw5c35210.png

 

Bug分析

本单元出现了不少的bug,特别是在第一单元,有一个接乘客的循环里忘记加上电梯内乘客人数少于6的判断条件,导致被很多的数据hack了。

第二次作业中整体完成情况不错,但是仍旧出现了bug,问题出在自由竞争的时候两个电梯接到了同一个人,也即之前提到过的从队列中拿取数据和删除数据要同时进行。

第三次作业的问题出在忘记在电梯接乘客之前判断这一部电梯是否能够送到乘客的目的地(其实我写代码的时候是记得的,写着写着就忘了。。。)。因为这个错误WrongAnswer了很多的数据点。

 

发现Bug

      可以通过在某一层同时投入大量的乘客来hack别人的电梯

 

 

心得体会

       虽然是第一次接触到多线程的任务,但是在实验代码的指导下完成的相对来说不算特别困难,一些需要注意和理解的地方实验代码都已经给出了,整体架构只需要自己在其上缝缝补补以及完成电梯类线程的编写即可。

  but这个单元的作业取得的性能分并不是很高,原因在我没有去优化我的调度策略,在第三次作业中也因为偷懒没有去使用dijstra算法。此外,在修改调度器后,对于共享变量的访问没有做到绝对安全,没有放在加锁区域,熟悉之后才发现了这些存在的问题。

Link to comment
Share on other sites