第二单元总结

一、同步块的设置与锁的选择

在第二单元的三次作业中,我只使用到了synchronized同步锁

同步块主要设置在几个地方:

  • 使用生产者消费者模式,在Input线程与调度器之间、调度器与电梯线程之间增加缓存队列(自定义的PassengerBuffer类)。在PassengerBuffer类中实现对队列的互斥访问,将相关函数使用关键字锁起来。这一部分也可以使用读写锁,性能会更好。

  • 在判断调度器是否结束时,需要使用调度器和输入之间的缓冲队列充当锁,将对队列的判断以及其它操作一起原子化,防止线程之间死锁。

  • 在电梯线程中,对于电梯和调度器之间的缓存的操作需要整体放在一个同步块中。

  • 由于在调度器中使用评价函数的方法,电梯的属性有多个线程可以访问,所以需要考虑互斥问题。在电梯的各个函数中根据必要加锁。

  • 处理双轿厢电梯碰撞问题时,需要为A、B两个电梯共享一把锁,在电梯移动时适当地加锁。

二、调度器设计与调度策略

调度器

调度器作为输入和电梯线程之间的系统,只负责将输入发送过来的乘客请求按照一定方法分配给多部电梯之一,并不负责reset等的分发。

调度器线程与其它线程之间的交互都是通过生产者消费者模式实现,将请求从缓冲中获取或发送到缓冲中。在进行评价函数的调用时,调度器线程还与电梯线程之间有着互斥的关系,需要互斥地访问电梯的属性。

单电梯调度策略

三次作业的单电梯调度策略都使用look算法,没有其他变化。

多电梯调度策略

从第二次作业开始需要考虑多电梯之间的调度策略。在思考第二次作业的实现时,首先想到的策略是根据一层层的条件筛选更合适的电梯。具体来说,首先不考虑超载的电梯,其次不考虑不顺路的电梯,最后在剩下的电梯里计算电梯接到乘客的时间消耗。如果没有剩下的电梯,则从不顺路的电梯中选择,同样也需要计算电梯接到乘客的时间消耗。而如果所有电梯都是超载电梯,则需要计算电梯超载了多少人,选择最少的那一台。在准备实现算法的时候发现,对于每一个电梯集合,其实都使用了一些数据计算,那么应该可以将三个集合的分数计算结合起来,通过设置不同的权重来计算得到最后的得分。于是写了如下的评价函数:

效果没有想象中那么好。在第二次作业中有一个数据得分趋近85,推测是有部分情况实现有误。

第三次作业同样沿用了这样的评价函数,函数本体并没有变换,只是在计算双轿厢电梯时选取上下两个轿厢中得分最低的那一个。同时在计算单个轿厢的分数时,如果该乘客的出发楼层并不在电梯运行路径上,则将分数设置为最大。

我的调度策略只考虑了尽量减小总时间以及乘客的等待时间,并没有将耗电量考虑在内,所以性能上没有做到极佳。

三、架构设计

第一次作业

第二次作业

第三次作业

从协作图来看,第一次作业到第二次作业的扩展中,在输入线程和电梯线程之间加入了新的一层,即调度器线程。其余部分并没有大规模的改变。

三次作业中稳定的内容就是输入线程,调度器线程。而电梯线程和策略等都是易变的内容,因为每一次作业的具体业务不同。

四、双轿厢碰撞问题

在双轿厢电梯的实现中,我让每一个轿厢都拥有着另一个轿厢的引用,使得能够方便得判断对方的位置。由于我使用了状态模式,每一个状态中具有move行为,所以这一部分我只在move函数中进行处理。主要部分如下:

在等待一定时间后,才进行避免碰撞的判断。首先需要对整个判断部分进行上锁,防止两个线程同时访问时都通过判断。如果自己想要前往换乘楼层而对方却已经在换乘楼层中则挂起,直到另一个电梯调用arrive()方法,其中用dcLock对象进行了唤醒。

五、bug与debug

在多线程相关的作业中,bug几乎都是由于线程不安全而引起的,并且通常表现为死锁。在第一次作业中产生的bug通常只与一部电梯有关,或者只是调度器和电梯之间的问题,通常可以使用多线程断点调试即可。但是在后两次作业中,线程之间的交互变得更加复杂,这种方式就不太适用了。在后两次作业中,我使用辅助输出来进行调试,通过分析输出之间的顺序关系寻找问题,这种调试方法最大的问题是由于输出产生的延迟导致原本由于线程不安全而产生的死锁并没有复现,所以需要大量地重复地测试。

六、心得体会

线程安全

在多线程编程中,线程安全十分地重要,如果不能很好地处理线程安全问题,容易导致业务逻辑出错甚至死锁。使用锁的时候,应当先充分考虑同步块的大小的合理性,避免重复嵌套锁以及使用过大的同步块。使用wait-notify模式而不是使用轮询方式。

在这三次作业中,我只使用到了synchronized同步锁,这是不太合理的地方。我还需要学习其它类型的锁的特点以及使用,交叉使用才能获得更好的效果。

层次化设计

这次作业整体上将系统分为电梯、调度器、输入三个层次,每个层次不需要考虑其它层次的具体实现,只需要调用相关方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值