OO 第二单元总结

李子涵-24371228 2026-04-27 00:33:22

一.同步块的设置和锁的选择

1. synchronized内置锁

在两个共享变量类请求队列RequestQueue和电梯井ShaftContext中对所有关键方法使用synchronized修饰,保证这些共享数据写和读的安全性。

2. 原子类变量AtomicInteger

RequestQueue中使用原子类变量assignedLoad来统计电梯负载数(即接受的乘客数),在接受请求时增加,乘客离开电梯时减少,用来让调度器判断分配给负载最少的电梯以及控制每个电梯请求的量,是个仅计数的轻量操作,用原子变量较高效。

总的来说,所有涉及共享资源读写的处理语句都被包裹在对应锁的同步范围内,大部分都是最简单的锁:方法上加synchronized修饰,保证代码的正确性,对并发效率应该有一定损失。

二.调度器设计

1. 调度器任务

  • 第一次作业:按要求中的电梯分配
  • 第二次作业:设计分配策略将请求分给电梯
  • 第三次作业:考虑双轿厢,只分配给对应楼层的电梯

2. 调度器与线程的交互

DispatchThreadInputThread生产的队列mainQueue中拿取请求,按策略分配给某个ElevatorThread对应的队列elevatorQueue,再让该电梯进程从对应队列取请求。

3. 调度策略

分配给当前负载数最少且满足双轿厢楼层要求的电梯,负载数由原子变量assignedLoad统计,如果所有能载客的电梯负载数达到6就让调度器休息,判断是否楼层要求如下:

private boolean canServe(int carId, int shaftId, int from, int to) {
        int state = f2Locks.get(shaftId).getState();
        if (state == ShaftContext.STATE_UPDATING) {
            return false;
        }
        if (carId <= 6) {
            if (state == ShaftContext.STATE_NORMAL) {
                return true;
            } else if (state == ShaftContext.STATE_DOUBLE ||
                    state == ShaftContext.STATE_RECYCLING) {
                return (from > 2 || (from == 2 && to > 2));
            }
        } else {
            if (state == ShaftContext.STATE_DOUBLE) {
                return (from < 2 || (from == 2 && to < 2));
            }
        }
        return false;
    }

三.bug和debug

1. 出现的bug

  • 超时:起初的电梯调度策略没有对电梯负载数做上限限制,导致一部电梯完成所有请求而超时。
  • 调度器进程提前结束:没有判断是否有电梯在维修之类的,导致最后一条命令是维修时,调度器看到没请求直接结束,而电梯维修时退回的请求无法被分配,没有被完成。
  • 分配请求给转为双轿厢的电梯:第三次作业时忘记在调度器中添加判断是否在更新和回收的代码。

2. debug

在代码中添加输出相关数据的代码,通过分析输出判断问题,而且注意在输出中显示是哪个进程的,不然完全分不清。

四.线程安全和层次化设计

想要保证线程安全,首先是保护好共享资源,读共享变量中所有读写的方法添加synchronized修饰,让数据在同一时间只有一个对象读或者写;然后是一些操作的原子性,比如判断和操作要一起完成,防止中间被其他进程插入出问题;接着是每个进程修改共享对象后要用notifyAll()让其他线程看到;最后是多个锁要注意锁的顺序保持一致,防止出现死锁的情况。
层次化设计主要是依照生产者消费者模型,InputThreadDispatchThreadmainQueue联系,DispatchThreadElevatorThreadelevatorQueue联系,两个对应的ElevatorThread之间用ShaftContext管理双轿厢的情况,总体架构非常清晰,将职责分离开来,易于维护。

五.大模型的使用

我主要使用Gemini作为辅助工具。我将整体架构与一些属性方法设计好,部分实现细节会询问大模型,以及帮助我debug以及判断锁相关的问题。总的来说大模型在多进程方面的表现还是比较差的,不太能发现一些锁或进程的问题,需要我去手动调试以及增加输出内容,但可以让它帮我梳理出每个进程的输出,便于我检查。

六.体验和感受

多进程的并发开发确实具有很大的考验,尤其是随机性太大了,有些bug甚至很难复现,可能我的代码现在还有某处存在没有把两个操作合成原子操作的问题,只是目前没被样例测出来。现在学习的锁还是比较粗的,性能较差一点,后续应该还需要更深入的学习,毕竟性能差距太大了,这在第二次作业给了我很深的印象,我本来以为不可能出现超时的问题的,没想到把请求全分给一个电梯后直接就超时了,和并行的差距巨大,现在的全添加synchronized修饰应该更接近串行一点,还是有很大优化空间的。

...全文
25 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

309

社区成员

发帖
与我相关
我的任务
社区描述
2026年北航面向对象设计与构造
java 高校
社区管理员
  • 孙琦航
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧