309
社区成员
发帖
与我相关
我的任务
分享采用了ReentrantLock,每当电梯试图更新自己的状态/更改RequestPool的数据时就要加锁
作业中并没有实现具体的调度器
调度策略是这样的:电梯在尝试人员上下、进行移动之前,会分别调用一次DecisionMaker.getInstance().update(this)来更新自己的状态
更新状态时,电梯通过RequestPool获取新的request,步骤如下:
首先对RequestPool加锁,然后遍历RequestPool中的所有乘客请求
对于每个乘客,通过模拟每一部电梯的运动,计算从当前时刻开始,在保留电梯自身与RequestPool的请求,且没有新的输入请求的情况下,哪一个电梯能够最快接到这个乘客,并把这个电梯标记为favoriteElevator
如果favoriteElevator就是电梯本身:1)电梯静止,则立即输出RECEIVE信息,然后去接这个乘客、2)电梯正在运动,则暂时不输出RECEIVE,把这个乘客留在RequestPool,直到电梯恰好能够接上这个乘客,或者电梯送完所有请求进入静止状态,再输出RECEIVE。这个过程中favoriteElelvator可能变成其他电梯
这个调度算法的开销非常大,直接导致了在第二次、第三次作业中的多个数据点出现CPU time limit exceeded,原因如下:
1.乘客会对每一部电梯进行模拟,在客流量较大的时候,一次模拟的计算次数非常多
2.电梯在人员上下、电梯移动前都会尝试从RequestPool里获取新的请求,每次进行这样的操作时,都会对RequestPool里所有的乘客进行更新
3.由于特殊的RECEIVE策略,RequestPool里经常会积压相当数量的请求,在极端数据的情况下,RequestPool里会有60多个乘客请求,而电梯的每次更新都会让所有乘客重新模拟一遍,找出最合适的电梯
死锁和轮询是最常出现的bug
最常见的情况就是线程1在持有锁A的时候,尝试去获取锁B,但是锁B已经被线程2占据了,所以线程1阻塞
然后线程2在持有锁B的情况下去获取锁A,因为线程1阻塞了,当然获取不到
最后两个线程就死锁了
解决方法是:尝试获取一把锁之前,先扔掉自己身上的所有锁
轮询出现的原因就是电梯线程休眠/结束的条件没有写全
我的debug方法是在特定位置输出调试信息
debug的难点在于当一个线程出现死锁/轮询时,其他线程还会运行一段时间,并产生新的调试输出,导致很难分辨出到底是哪个线程出了问题
要实现线程安全主要是考虑是否会出现死锁
我的作业层次化设计做的不太好,因为RequestPool这个类除了负责存储请求外,还有负责电梯的休眠,而电梯的休眠显然让Elevator类本身负责更合适
模型名称:Gemeni
分工:对于一些不清楚的代码细节,问一下AI是怎么回事,以及让AI检查哪里有bug
感受:跟AI对话三轮下来不红温的是这个👍,个人感觉AI不算太好用,也有可能是我的架构设计比较差,有很多地方需要改进
最困难的一个月,好在终于熬过去了
写作业二的时候改bug一直改到凌晨两点半,成功突破个人熬夜记录
建议在作业结束后提供一个示例的代码框架,可以参照这个框架对自己的代码进行修改